maven依赖
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- mysql连接驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
mybatis核心组件:
SqlSessionFactoryBuilder(构造器):它会根据配置或者代码来生成SqlSessionFactory,采用的是分步构建的Builder模式。
SqlSessionFactory(工厂接口):依靠它来生成SqlSession。使用的是工厂模式。
SqlSession(会话):一个既可以发送sql执行返回结果,也可以获取Mapper的接口。
Sql Mapper(映射器):由JAVA接口和XML(或注解)构成,需要给出对应的sql和映射规则,它负责发送sql去执行并返回结果。
一、使用xml配置文件构建SqlSessionFactory
配置文件内容:mybatis配置文件详解 http://www.mybatis.org/mybatis-3/zh/configuration.html
<?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>
<property name="password" value="root"/>
</properties>-->
<settings>
<!--自动映射-->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<!--开启自动驼峰命名映射-->
<!--<setting name="mapUnderscoreToCamelCase" value="true"/>-->
</settings>
<!-- 别名 -->
<typeAliases>
<!--通过扫包-->
<package name="com.mybatis"/>
<!--<typeAlias alias="user" type="com.mybatis.core.User"/>-->
</typeAliases>
<!--数据库配置-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--映射器-->
<mappers>
<!--使用注解实现映射器-->
<!--<mapper class="com.mybatis.dao.UserAnnotationMapper"/>
<package name="com.mybatis.dao"/>-->
<!--使用xml实现映射器(优先,同时定义会覆盖注解方式)-->
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
Mybatis映射器:
<?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.mybatis.dao.UserMapper">
<resultMap type="user" id="ResultMap">
<result property="id" column="id" jdbcType="VARCHAR"/>
<result property="userName" column="user_name" jdbcType="VARCHAR"/>
<result property="password" column="user_password" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column">
id,user_name,user_password
</sql>
<sql id="UserCondition">
<where>
1= 1
<if test="userName != null and userName != ''">
AND user_name = #{userName}
</if>
</where>
</sql>
<select id="findUserByName" parameterType="java.lang.String" resultMap="ResultMap">
select
<include refid="Base_Column"/>
from p_user where user_name = #{userName}
</select>
<select id="findUserList" resultMap="ResultMap" parameterType="user">
SELECT
<include refid="Base_Column"/>
FROM p_user
<include refid="UserCondition"/>
</select>
<!--自动映射,无需resultMap跟对象映射-->
<select id="findUserById" parameterType="java.lang.String" resultType="user">
select
id as id,
user_name as userName,
user_password as password
from p_user where id = #{id}
</select>
<select id="findUserByIdCp" resultType="user">
select
id as id,
user_name as userName,
user_password as password
from p_user where id = #{userId}
</select>
<update id="updateUser" parameterType="user">
update p_user set user_name = #{userName},user_password = #{password} WHERE id = #{id}
</update>
<insert id="saveUser" parameterType="user">
insert into p_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null and id != ''">
id,
</if>
<if test="userName != null and userName != ''">
user_name,
</if>
<if test="password != null and password != ''">
user_password,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null and id != ''">
#{id},
</if>
<if test="userName != null and userName != ''">
#{userName},
</if>
<if test="password != null and password != ''">
#{password},
</if>
</trim>
</insert>
<select id="updateTest" parameterType="user">
insert into p_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null and id != ''">
id,
</if>
<if test="userName != null and userName != ''">
user_name,
</if>
<if test="password != null and password != ''">
user_password,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null and id != ''">
#{id},
</if>
<if test="userName != null and userName != ''">
#{userName},
</if>
<if test="password != null and password != ''">
#{password},
</if>
</trim>
</select>
<select id="findByRowBounds" resultType="user">
select
id as id,
user_name as userName,
user_password as password
from p_user
</select>
</mapper>
package com.mybatis.dao;
import com.mybatis.core.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.session.RowBounds;
import java.util.List;
/**
* @author zqq
*/
public interface UserMapper {
User findUserByName(String userName);
List<User> findUserList(User user);
void updateUser(User user);
void saveUser(User user);
void updateTest(User user);
User findUserById(String id);
User findUserByIdCp(@Param("userId") String id);
/**
* 分页查询
* @param user user参数
* @param rowBounds 分页参数,只需要加在接口上mybatis自动识别
* @return
*/
List<User> findByRowBounds(@Param("params") User user, RowBounds rowBounds);
}
构建SqlSession发送sql:
@Test
public void demo1(){
//配置文件位置
String resource = "conf/mybatis-config.xml";
try {
//读取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//通过SqlSessionFactoryBuilder的build方法构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//打开会话SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//获取mapper映射器执行sql
List<User> list = userMapper.findUserList(new User());
list.forEach(u -> {
//输出查询出的信息
System.out.println(u.toString());
});
} catch (IOException e) {
e.printStackTrace();
}
}
事务管理器TransactionManager
TransactionManager提供了两个实现类,需要实现Transaction接口org.apache.ibatis.transaction.Transaction
public interface Transaction {
Connection getConnection() throws SQLException;
//提交事务
void commit() throws SQLException;
//回滚
void rollback() throws SQLException;
//关闭
void close() throws SQLException;
Integer getTimeout() throws SQLException;
}
TransactionManager提供了两个实现类:JdbcTransaction和ManagedTransaction。都继承了Transaction接口
配置开启事务:
<!--数据库配置-->
<environments default="development">
<environment id="development">
<!--jdbc方式-->
<transactionManager type="JDBC"/>
<!--<transactionManager type="MANAGED"/>-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
JDBC使用JdbcTransactionFactory生成的JdbcTransaction对象实现。它是以JDBC方式对数据库的提交和回滚进行操作。
MANAGED使用ManagedTransactionFactory生成的ManagedTransaction对象实现。它的提交和回滚不用任何操作,而是把事务交给容器处理。
/**
* 事务
*/
@Test
public void test(){
SqlSessionFactory sqlSessionFactory = null;
String resource = "conf/mybatis-config.xml";
SqlSession sqlSession = null;
try {
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
} catch (IOException e) {
e.printStackTrace();
}
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
try {
User user = new User();
user.setId(UUID.randomUUID().toString().replaceAll("-",""));
user.setUserName("testName");
user.setPassword("123456");
userMapper.saveUser(user);
//报错回滚事务
//System.out.println(1/0);
sqlSession.commit();
//提交事务
}catch (Exception e){
e.printStackTrace();
//事物回滚
sqlSession.rollback();
}finally {
//关闭会话
sqlSession.close();
}
}
自定义事务:
定义事务类,继承JdbcTransaction类,实现Transaction接口(不实现也可以,父类JdbcTransaction已经实现),重写方法。
/**
* 自定义事务类
*/
public class MyTransaction extends JdbcTransaction {
public MyTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
super(ds, desiredLevel, desiredAutoCommit);
}
@Override
public Connection getConnection() throws SQLException {
return super.getConnection();
}
@Override
public void commit() throws SQLException {
System.out.println("自定义事务commit");
super.commit();
}
@Override
public void rollback() throws SQLException {
System.out.println("自定义事务rollback");
super.rollback();
}
@Override
public void close() throws SQLException {
System.out.println("自定义事务close");
super.close();
}
@Override
protected void setDesiredAutoCommit(boolean desiredAutoCommit) {
super.setDesiredAutoCommit(desiredAutoCommit);
}
@Override
protected void resetAutoCommit() {
super.resetAutoCommit();
}
@Override
protected void openConnection() throws SQLException {
super.openConnection();
}
@Override
public Integer getTimeout() throws SQLException {
return super.getTimeout();
}
public MyTransaction(Connection connection) {
super(connection);
}
}
定义事务工厂,实现TransactionFactory事务工厂接口,将返回的事务类改成自定义的事务类。
/**
* 自定义事务工厂
*/
public class MyTransactionFactory implements TransactionFactory {
@Override
public void setProperties(Properties properties) {
}
@Override
public Transaction newTransaction(Connection connection) {
return new MyTransaction(connection);
}
@Override
public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel transactionIsolationLevel, boolean b) {
return new MyTransaction(dataSource,transactionIsolationLevel,b);
}
}
修改配置文件,配上自定义的事务工厂:
<!--数据库配置-->
<environments default="development">
<environment id="development">
<!--<transactionManager type="JDBC"/>-->
<!--自定义事务配置-->
<transactionManager type="com.mybatis.transaction.MyTransactionFactory"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
测试回滚成功:
@Test
public void test(){
SqlSessionFactory sqlSessionFactory = null;
String resource = "conf/mybatis-config.xml";
SqlSession sqlSession = null;
try {
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSession = sqlSessionFactory.openSession();
} catch (IOException e) {
e.printStackTrace();
}
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
try {
User user = new User();
user.setId(UUID.randomUUID().toString().replaceAll("-",""));
user.setUserName("name");
user.setPassword("pwd");
userMapper.saveUser(user);
//报错回滚事务
System.out.println(1/0);
sqlSession.commit();
//提交事务
}catch (Exception e){
e.printStackTrace();
//事物回滚
sqlSession.rollback();
}finally {
//关闭会话
sqlSession.close();
}
}