Java连接数据库工具类的变化

(一、DBUtil工具类)

package com.aishang.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DbUtil {
	private static String url = "jdbc:mysql://localhost:3306/day11";
	private static String name = "root";
	private static String password = "root";
	private static Connection conn;
	static {
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	//从数据库中获取连接
	public static Connection getConnection() {
		try {
			conn = DriverManager.getConnection(url, name, password);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return conn;
	}
	//将连接关闭
	public static void close(Connection conn, PreparedStatement ps, ResultSet rs) {
		try {
			if (rs != null)
				rs.close();
			if (ps != null)
				ps.close();
			if (conn != null)
				conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

(二、DBCPUtil工具类)

package com.aishang.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

public class DBCPUtil {
	private static DataSource ds = null;
	//连接驱动
	static{
		Properties prop = new Properties();
		try {
			prop.load(DBCPUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"));
			ds = BasicDataSourceFactory.createDataSource(prop);
		} catch (Exception e) {
			throw new ExceptionInInitializerError("初始化错误,请检查配置文件");
		}
	}
	//从数据库中获得连接 
	public static Connection getConnection(){
		try {
			return ds.getConnection();
		} catch (SQLException e) {
			throw new RuntimeException("服务器忙。。。");
		}
	}
	//将连接关闭
	public static void close(Connection conn, PreparedStatement ps, ResultSet rs) {
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			rs = null;
		}
		if(ps!=null){
			try {
				ps.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			ps = null;
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			conn = null;
		}
	}
}

(三、ThreadLocal工具类)

package com.aishang.util;
import java.sql.Connection;
import java.sql.SQLException;
public class ManageThreadLocal {
	private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
	//将Connection对象保存到线程对象中
	public static Connection getConnection(){
		Connection conn = tl.get();
		if(conn==null){
			conn = DBCPUtil.getConnection();
			tl.set(conn);
		}
		return conn;
	}
	//设置事务为手动提交
	public static void setAutoCommit(){
		try {
			getConnection().setAutoCommit(false);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	//提交事务
	public static void commit(){
		try {
			getConnection().commit();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	//回滚事务
	public static void rollback(){
		try {
			getConnection().rollback();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	//将conn还回池子,并将对象与线程解绑
	public static void close(){
		try {
			getConnection().close();
			tl.remove();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

相比于前面的两种方式,ThreadLocal的优点在于:事物的操作

事务操作,需要将不同的子业务放到同一个Connection,事务是依赖于Connection的业务操作,需要将不同的子业务放到同一个Connection,事务是依赖于Connection的。

解决方式I:Dao层,需要注入进来类级别的成员变量Connection,保证,查询和修改方法都是用的是同一Connection对象。问题得以解决,但是产生一个很大的问题:Connection对象不应该出现在service层,应该出现在dao层的代码出现在了service层,但是为了保证传入dao层的Connection是一个,并且保证事务操作,没有办法只能出现在service层,因此这不是一个好的解决方案。

解决方式II:增加ThreadLocal工具类

ThreadLocal介绍

代码模拟:

思路:不同的用户访问服务器,要开启不同的线程,如果让当前某一个线程,操作同一个Connection对象,可以保证Service层以及两次调用dao层完成账户修改的功能,使用的都是一个Connection对象,即:与当前线程绑定的Connection对象,这就具备了事务操作的基础(同一个Connection对象)。怎样让当前的线程记录并绑定同一个Connection对象?使用Java内置好的ThreadLocal类(封装了一种结构,并提供操作方法)

public int addNews(News news){
		int res = 0;
		int id = -1;
		try {
			/*conn = DBCPUtil.getConnection();过去的写法,不能保证事务中对Connection一致的要求*/
			String sql = "insert into tb_news values(default,?,?,?,?,?,?)";
			ps = ManageThreadLocal.getConnection().prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);//为事务获得统一Connection对象
			ps.setString(1, news.getTitle());
			ps.setString(2, news.getContent());
			ps.setInt(3,news.getTypeId());
			ps.setInt(4, news.getFlag());
			ps.setString(5, news.getCreateTime());
			ps.setInt(6, news.getUserId());
			ps.executeUpdate(); 
			rs=ps.getGeneratedKeys();//这一句代码就是得到插入的记录的id
			while(rs.next()){
			    id=rs.getInt(1);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			DBCPUtil.close(null, ps, rs);//关闭时不可以关闭统一的conn对象,开着供其他人使用
		}
		return id;//添加新闻文本后需要立刻获得刚添加的新闻的id,为新闻图片添加得到最新nid
	}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值