框架还没搭好的请看MyBatis入门
MyBatis工具类
由于频繁的加载配置文件创建对象工厂获取会话,如果我每个接口都需要重新写一遍这样的代码就会显得代码量很多,所以我写了一个MyBatis工具类,把这些重复的代码给封装起来。
MyBatis工具类
增、删、改、查
通过使用工具类来完成对数据库的操作
UserDao
public interface UserDao {
//根据主键id查询
User fainQuery(int id);
//修改
int update(@Param("id")int id,@Param("name")String name);
//新增
int insert(User user);
//删除
int delete(int id);
//查询全部
List<User> selectAll();
//获取总条数
int count();
}
1.@Param注解一般是用在传递多个参数的场景里,这样方便我们知道传递的是哪个参数。
2.还有一种方式在xml里用 #[0],#[1]… 这样的方式是根据接口的参数列表来按顺序传递的
UserDaoImpl
public class UserDaoImpl implements UserDao {
//获取接口实现类对象
private UserDao userDao = (UserDao)SqlUtils.getMapper(UserDao.class);
@Override
public User fainQuery(int id) {
// TODO Auto-generated method stub
return userDao.fainQuery(id);
}
@Override
public int update(int id,String name) {
// TODO Auto-generated method stub
return userDao.update(id,name);
}
@Override
public int insert(User user) {
// TODO Auto-generated method stub
return userDao.insert(user);
}
@Override
public List<User> selectAll() {
// TODO Auto-generated method stub
return userDao.selectAll();
}
@Override
public int count() {
// TODO Auto-generated method stub
return userDao.count();
}
@Override
public int delete(int id) {
// TODO Auto-generated method stub
return userDao.delete(id);
}
}
UserMapper
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.UserDao">
<select id = "fainQuery" parameterType="int" resultType="user">
select * from user where id = #{id}
</select>
<update id="update" parameterType = "user">
update user set name = #{name} where id = #{id}
</update>
<insert id = "insert" parameterType="user">
insert user(id,name,age)
value(#{id},#{name},#{age})
</insert>
<select id = "selectAll" resultType="user">
select * from user
</select>
<select id="count" resultType="int">
select count(*) from user
</select>
<delete id = "delete" parameterType="int">
delete from user where id = #{id}
</delete>
</mapper>
- parameterType:传递过来的参数类型
- resultType:返回的参数类型
delete,insert,update是没有resultType的因为返回的都是int类型。
上面这两个是常用的。
测试:
public class Demo {
//获取实体类对象
private UserDao userDao = new UserDaoImpl();
/**
* 根据主键id获取一条数据
*/
@Test
public void test1(){
User user = userDao.fainQuery(2);
System.out.println(user.getName());
}
/**
* 修改
*/
@Test
public void test2(){
int open = userDao.update(2,"huisbsbsbs");
SqlUtils.commit();
System.out.println(open);
}
/**
* 新增
*/
@Test
public void test3(){
User user = new User();
user.setId(3);
user.setName("周总");
user.setAge(24);
int open = userDao.insert(user);
SqlUtils.commit();
System.out.println(open);
}
/**
* 查询全部
*/
@Test
public void test4(){
List<User> list = userDao.selectAll();
for (User user : list) {
System.out.println(user.getId());
System.out.println(user.getName());
System.out.println(user.getAge());
System.out.println();
}
}
/**
* 获取总数
*/
@Test
public void test5(){
int count = userDao.count();
System.out.println(count);
}
/**
* 删除
*/
public void test6(){
int open = userDao.count();
SqlUtils.commit();
System.out.println(open);
}
}
只有新增,删除,修改才会改变数据 才需要commit(提交事务)
事务管理
1.什么是事务
事务是一个不可分割工作单位,事务中的操作要么都做,要么都不做。事务可大可小,一个事务在关系数据库中,可以是一条SQL语句也可以是一组SQL语句或者一个程序。
2.MyBatis的两种事务管理机制
1.使用JDBC的事务管理机制
利用java.sql.Connection来完成对事务提交(commit)、回滚(rollback)、清空(close).
2.使用MANAGED的事务管理机制
MyBatis自身不会管理事务,将管理事务的操作交给Web容器或者Spring容器来实现对事务的管理。
3.MyBatis事务管理的配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 加载外部资源文件 -->
<properties resource="config/db.properties"/>
<!-- 类型别名 -->
<typeAliases>
<package name="com.action"/>
</typeAliases>
<!-- 配置数据源 -->
<environments default="development">
<environment id="development">
<!--配置JDBC手动管理事务 -->
<transactionManager type="JDBC"/>
<!--配置MANAGED自动管理事务-->
<!--<transactionManager type="MANAGED"/>-->
<dataSource type="POOLED">
<property name="url" value="${jdbc.url}"/>
<property name="driver" value="${jdbc.driver}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 配置映射接口 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
environment节点配置连接数据库的信息,其子节点transactionManager 的type决定我们使用什么事务管理机制。
4.MyBatis的Transaction
Transaction接口是对两种事务的管理器进行的一个约束
/**
* 包装数据库连接
* 处理连接生命周期,包括:它的创建,准备,提交/回滚和关闭
*
* @author Clinton Begin
*/
public interface Transaction {
/**
* 检索内部数据库连接
* @return DataBase connection
* @throws SQLException
*/
Connection getConnection() throws SQLException;
/**
* 提交内部数据库连接。
* @throws SQLException
*/
void commit() throws SQLException;
/**
* 回滚内部数据库连接。
* @throws SQLException
*/
void rollback() throws SQLException;
/**
* 关闭内部数据库连接。
* @throws SQLException
*/
void close() throws SQLException;
/**
* 如果设置了,则获取事务超时
* @throws SQLException
*/
Integer getTimeout() throws SQLException;
}
5.Transaction的两个实现类
JdbcTransaction
JdbcTransaction直接使用JDBC的提交和回滚事务管理机制。它依赖与从dataSource中获取连接connection对象来管理Transaction的作用域。connection对象的获取被延迟到调用getConnection,如果autoCommit设置为on(开启状态),它会忽略commit和rollback.(看下面的代码)
public class JdbcTransaction implements Transaction {
private static final Log log = LogFactory.getLog(JdbcTransaction.class);
//数据库连接
protected Connection connection;
//数据源
protected DataSource dataSource;
//隔离级别
protected TransactionIsolationLevel level;
//是否为自动提交
protected boolean autoCommmit;
public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
dataSource = ds;
level = desiredLevel;
autoCommmit = desiredAutoCommit;
}
public JdbcTransaction(Connection connection) {
this.connection = connection;
}
@Override
public Connection getConnection() throws SQLException {
if (connection == null) {
openConnection();
}
return connection;
}
@Override
public void commit() throws SQLException {
if (connection != null && !connection.getAutoCommit()) {
if (log.isDebugEnabled()) {
log.debug("Committing JDBC Connection [" + connection + "]");
}
connection.commit();
}
}
@Override
public void rollback() throws SQLException {
if (connection != null && !connection.getAutoCommit()) {
if (log.isDebugEnabled()) {
log.debug("Rolling back JDBC Connection [" + connection + "]");
}
connection.rollback();
}
}
@Override
public void close() throws SQLException {
if (connection != null) {
resetAutoCommit();
if (log.isDebugEnabled()) {
log.debug("Closing JDBC Connection [" + connection + "]");
}
connection.close();
}
}
protected void setDesiredAutoCommit(boolean desiredAutoCommit) {
try {
if (connection.getAutoCommit() != desiredAutoCommit) {
if (log.isDebugEnabled()) {
log.debug("Setting autocommit to " + desiredAutoCommit + " on JDBC Connection [" + connection + "]");
}
connection.setAutoCommit(desiredAutoCommit);
}
} catch (SQLException e) {
// Only a very poorly implemented driver would fail here,
// and there's not much we can do about that.
throw new TransactionException("Error configuring AutoCommit. "
+ "Your driver may not support getAutoCommit() or setAutoCommit(). "
+ "Requested setting: " + desiredAutoCommit + ". Cause: " + e, e);
}
}
protected void resetAutoCommit() {
try {
if (!connection.getAutoCommit()) {
// MyBatis does not call commit/rollback on a connection if just selects were performed.
// Some databases start transactions with select statements
// and they mandate a commit/rollback before closing the connection.
// A workaround is setting the autocommit to true before closing the connection.
// Sybase throws an exception here.
if (log.isDebugEnabled()) {
log.debug("Resetting autocommit to true on JDBC Connection [" + connection + "]");
}
connection.setAutoCommit(true);
}
} catch (SQLException e) {
if (log.isDebugEnabled()) {
log.debug("Error resetting autocommit to true "
+ "before closing the connection. Cause: " + e);
}
}
}
protected void openConnection() throws SQLException {
if (log.isDebugEnabled()) {
log.debug("Opening JDBC Connection");
}
connection = dataSource.getConnection();
if (level != null) {
connection.setTransactionIsolation(level.getLevel());
}
setDesiredAutoCommit(autoCommmit);
}
@Override
public Integer getTimeout() throws SQLException {
return null;
}
}
ManagedTransaction
这个实现类中没有具体的实现commit和rollback方法,ManagedTransaction是让容器来管理Transaction的生命周期,使用commit和rollback也没关系因为没用具体的实现,它将事务管理全权交给了容器。(看下面的代码)
public class ManagedTransaction implements Transaction {
private static final Log log = LogFactory.getLog(ManagedTransaction.class);
//数据库连接
protected Connection connection;
//数据源
protected DataSource dataSource;
//隔离级别
protected TransactionIsolationLevel level;
//是否为自动提交
protected boolean autoCommmit;
public ManagedTransaction(Connection connection, boolean closeConnection) {
this.connection = connection;
this.closeConnection = closeConnection;
}
public ManagedTransaction(DataSource ds, TransactionIsolationLevel level, boolean closeConnection) {
this.dataSource = ds;
this.level = level;
this.closeConnection = closeConnection;
}
@Override
public Connection getConnection() throws SQLException {
if (this.connection == null) {
openConnection();
}
return this.connection;
}
@Override
public void commit() throws SQLException {
// Does nothing
}
@Override
public void rollback() throws SQLException {
// Does nothing
}
@Override
public void close() throws SQLException {
if (this.closeConnection && this.connection != null) {
if (log.isDebugEnabled()) {
log.debug("Closing JDBC Connection [" + this.connection + "]");
}
this.connection.close();
}
}
protected void openConnection() throws SQLException {
if (log.isDebugEnabled()) {
log.debug("Opening JDBC Connection");
}
this.connection = this.dataSource.getConnection();
if (this.level != null) {
this.connection.setTransactionIsolation(this.level.getLevel());
}
}
@Override
public Integer getTimeout() throws SQLException {
return null;
}
}