最近手上一个小项目使用框架不划算,全部使用jdbc访问数据库。
但是在建立数据库连接池和service层conn的事务控制,不是很明白我的DBUtil类
public class DBUtil {
private static Logger logger = Logger.getLogger(DBUtil.class);
private static DataSource ds;
private static ThreadLocal<Connection> connLocal = new ThreadLocal<Connection>();

static{
Properties props = new Properties();
try {
props.load(DBUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"));
ds = BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
logger.error("读取文件出现异常,异常信息为:"+e.getMessage());
}
}

public static Connection getConnection(){
Connection conn = connLocal.get();
if(conn==null){
try {
conn = ds.getConnection();
} catch (Exception e) {
logger.error("获取数据库连接出现异常,异常信息为:"+e.getMessage());
}
connLocal.set(conn);
}
return conn;
}

public static void closeConnection(){
Connection conn = connLocal.get();
connLocal.set(null);
if(conn!=null){
try {
conn.close();
} catch (Exception e) {
logger.error("关闭数据库连接出现异常,异常信息为:"+e.getMessage());
}
}
}
}在service成我需要对一些业务进行事务控制。
Connection conn = null;
try {
conn = DBUtil.getConnection();

conn.setAutoCommit(false);

availJourneyDao.saveAvailJourney(availJourneyModel,conn);

List<Flight> list = aj.getFlightList();
for (Flight flight : list) {
FlightModel flightModel = new FlightModel();
flightModel.setArrivalAirport(flight.getArrivalAirport());
flightModel.setArrivalDate(flight.getArrivalDate());
flightModel.setArrivalTime(flight.getArrivalTime());
flightModel.setAvailJourneyId(availJourneyId);
flightModel.setDepartureAirport(flight.getDepartureAirport());
flightModel.setDepartureDate(flight.getDepartureDate());
flightModel.setDepartureTime(flight.getDepartureTime());
flightModel.setEquipment(flight.getEquipment());
flightModel.setFlightId(UUID.getUUID());
flightModel.setFlightNumber(flight.getFlightNumber());
flightModel.setMarketingAirline(flight.getMarketingAirline());
flightModel.setResBookDesigList(flight.getResBookDesigList());
flightDao.saveFlight(flightModel,conn);
}
conn.commit();
} catch (Exception e) {
logger.error("访问数据库出现异常,异常信息为:"+e.getMessage());
try {
conn.rollback();
} catch (Exception e2) {
logger.error("回滚异常:"+ e2.getMessage());
}
}finally{
try {
conn.close();
} catch (Exception e2) {
logger.error("关闭异常:"+ e2.getMessage());
}
}这是我现在使用的事务控制方法,但是现在有一个问题就是:在关闭connection是使用拦截器两者的关闭会不会冲突(这里不太确定),也就是我的service事务还没有完成拦截器就给我吧connection关闭了。还有我在网上看到了一些 localThread类中绑定事务管理,但是我不是很理解如何保证在多个dao类中,多个方法等到的是同一个connection。 这样让我感觉localThread的事务管理不是很稳定。
jdbc事务LocalThreadconnectionjava

解决方案 »

  1.   

    拼写拼反了..是ThreadLocal通过ThreadLocal 可以为每个线程保存一个数据库连接 这样在多线程环境下连接就不会冲突 单个线程的连接管理还很难么?首先将关闭连接的操作从普通的业务代码中剔除掉 通过动态代理或者过滤器将每次请求变成一次事务 比如进入过滤器 开启事务 所有的业务操作执行的有关数据库的操作都通过你提供的接口去执行 保证了没有人滥用或者非法更改Connection的状态 在一次请求结束后在过滤器后者代理中再释放掉连接 Spring就是这样做的 当然 他支持多种策略 我举的只是个简单的例子
      

  2.   

    @BearKin
    ThreadLocal这样的错误犯的很不应该,你的解答给了我很大的帮助,谢谢的你回答。
    但同时我又有了一些疑惑:一次请求是一个线程、“每个线程保存一个数据库连接”这句话的意思是一个线程中只可能有一个connection,可以这么理解吗? 还有就是“ 通过动态代理或者过滤器将每次请求变成一次事务”,有没有demo或者网址给我参考一下啊,
     谢谢你的解答
      

  3.   

    一个请求会被分配给一个线程处理(我们假设这个项目是个运行在J2EE应用服务器的项目)
    一个线程持有一个连接(你也可以持有很多连接 问题是要来干嘛?)
    DEMO的话 你看API 自己就能搞出一个 
      

  4.   

    你的一次请求只需要一个connection就可以了啊,因为你的操作步骤都是按照顺序来执行的,除非你开了很多个子线程,这时候来做事务控制貌似就没有什么意义了,你说是吧