Jdbcutils代码
package com.xzh.utils;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* @Author Lin
* @CreateTime 2021/5/7 19:14
*/
public class JdbcUtils {
//创建一个ThreadLocal类 里面值得类为Connection类
private static ThreadLocal< Connection > conns = new ThreadLocal<>();
private static DruidDataSource dataSource;
static {
try {
Properties properties = new Properties();
//读取配置文件
InputStream resourceAsStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
//加载数据
properties.load(resourceAsStream);
//获取链接
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取链接
*
* @return //返回null说明获取连接失败
*/
public static Connection getConnection() {
//从ThreadLocal中得到链接
Connection conn = conns.get();
//若果没有就创建一个链接
if (conn == null) {
try {
//从datasource中获取一个链接
conn = dataSource.getConnection();
//设置为手动提交
conn.setAutoCommit(false);
//保存链接到ThreadLocal中
conns.set(conn);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return conn;
}
/**
* 事务回滚
*/
public static void commitAndClose() {
//从线程中得到一个数值
Connection connection = conns.get();
if (connection != null) {//如果不等于空就说名使用过这个链接
try {
connection.commit();//事务提交
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
try {
connection.close();//关闭连接
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
conns.remove();//必须加上这个因为tomcat底层使用了线程池技术
}
/**
* 事务回滚
*/
public static void rollbackAndClose() {
//从线程中得到一个数值
Connection connection = conns.get();
if (connection != null) {//如果不等于空就说名使用过这个链接
try {
connection.rollback();//事务回滚
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
try {
connection.close();//关闭连接
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
conns.remove();//必须加上这个因为tomcat底层使用了线程池技术
}
}
BaseDao代码:
package com.xzh.dao.impl;
import com.xzh.utils.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* @Author Lin
* @CreateTime 2021/5/7 21:09
*/
public abstract class BaseDao {
//DBUtils操作数据库
private QueryRunner queryRunner = new QueryRunner();
public int update(String s, Object... objects) {
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.update(connection, s, objects);
} catch (SQLException throwables) {
throwables.printStackTrace();
//这里必须往上抛 如果不往上抛的话 外面不能捕获异常
// 就不能判断到底是提交还是回滚
throw new RuntimeException(throwables);
}
}
/**
* @param type
* @param sql
* @param args
* @param <T>
* @return
*/
public < T > T queryForOne(Class< T > type, String sql, Object... args) {
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.query(connection, sql, new BeanHandler< T >(type), args);
} catch (SQLException throwables) {
throwables.printStackTrace();
//这里必须往上抛 如果不往上抛的话 外面不能捕获异常
// 就不能判断到底是提交还是回滚
throw new RuntimeException(throwables);
}
}
/**
* @param type
* @param sql
* @param args
* @param <T>
* @return
*/
public < T > List< T > queryForList(Class< T > type, String sql, Object... args) {
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.query(connection, sql, new BeanListHandler< T >(type), args);
} catch (SQLException throwables) {
throwables.printStackTrace();
//这里必须往上抛 如果不往上抛的话 外面不能捕获异常
// 就不能判断到底是提交还是回滚
throw new RuntimeException(throwables);
}
}
/**
* 查询一行一列的东西
*
* @param sql
* @param args
* @return
*/
public Object queryForSingleValue(String sql, Object... args) {
Connection connection = JdbcUtils.getConnection();
try {
return queryRunner.query(connection, sql, new ScalarHandler(), args);
} catch (SQLException throwables) {
throwables.printStackTrace();
//这里必须往上抛 如果不往上抛的话 外面不能捕获异常
// 就不能判断到底是提交还是回滚
throw new RuntimeException(throwables);
}
}
public int queryId(String sql,Object username){
Connection connection = JdbcUtils.getConnection();
try {
return (int)queryRunner.query(connection, sql, new ScalarHandler(), username);
} catch (SQLException throwables) {
throwables.printStackTrace();
//这里必须往上抛 如果不往上抛的话 外面不能捕获异常
// 就不能判断到底是提交还是回滚
throw new RuntimeException(throwables);
}
}
}
然后利用filter过滤器给每一个需要的方法加上过滤器
package com.xzh.filter;
import com.xzh.utils.JdbcUtils;
import jakarta.servlet.*;
import java.io.IOException;
/**
* @Author XuZhuHong
* @CreateTime 2021/5/15 15:41
*/
public class TransactionFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
JdbcUtils.commitAndClose();//没有异常就提交
} catch (Exception e) {
JdbcUtils.rollbackAndClose();//有异常就提交
e.printStackTrace();
}
}
@Override
public void destroy() {
}
}
在web.xml中给需要回滚的方法配置
<!-- 给所有的类加上事务回滚 -->
<filter>
<!-- 设置别名-->
<filter-name>TransactionFilter</filter-name>
<!-- 设置过滤器的位置-->
<filter-class>com.xzh.filter.TransactionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TransactionFilter</filter-name>
<!-- 设置需要配置给谁 /*表示工程下的所有-->
<url-pattern>/*</url-pattern>
</filter-mapping>
注意使用这个的时候 所有异常 必须向外抛
如下代码
catch (SQLException throwables) {
throwables.printStackTrace();
//这里必须往上抛 如果不往上抛的话 外面不能捕获异常
// 就不能判断到底是提交还是回滚
throw new RuntimeException(throwables);
}