MyBatis技术(二)

一、接口映射

通过接口方式来映射到指定SQL之后,那么就可以通过操作接口的方法来访问数据库了,这种方式更加符合Java面向接口编程的要求。

1.1 定义映射接口

在映射文件中所在包下定义一个接口类,该接口负责提供操作数据库的方法。

public interface ProductMapper {
	
	public Product select(int id);
	
}

虽然接口名可以是任意名字。但是一般使用“表名(首字母大写)+Mapper”的命名方式。、

1.2 把映射接口的名字作为映射文件的唯一标识

在映射文件mapper节点指定namespace属性,该属性的值为映射接口的完整路径。例如:

<mapper namespace="com.xxx.mybatisqs.mapper.ProductMapper">
	...
</mapper>

namespace属性可以作为该映射文件的唯一标识。通过namespace属性可以调用该映射文件中定义的sql命令。

1.3 配置映射接口

修改mybatis-config.xml配置文件,加入映射接口的配置。

<mappers>
	<mapper class="com.xxx.mybatisqs.mapper.ProductMapper"/>
</mappers>

1.4 测试

第一步:获取SqlSession对象;
第二步:调用SqlSession对象的getMapper方法获取映射接口的代理;
第三步:调用接口方法;
第四步:提交事务;
第五步:关闭sqlSession;
在这里插入图片描述

二、MyBatis零配置

MyBatis也支持使用注解方式配置SQL。而且在实际项目中,推荐使用注解配置方式。使用注解配置方式后,可以不再提供映射文件。

2.1 @Select和@ResultType

select注解用于指定要执行的sql语句。resultType注解用于指定映射的结果类型。

@Select("select product_id as id, product_name as name, product_price as price "
			+ "from product where product_id = #{id}")
@ResultType(Product.class)
public Product select(int id);

2.2 @Results和@Result

如果要自己指定实体的映射关系,可以使用@Results注解。

  • @Results可以用来自定义查询结果的映射关系。
  • @Result用于指定实体属性与表字段的对应关系。

例如:

扫描二维码关注公众号,回复: 9570307 查看本文章
@Select("select * from product where product_id = #{id}")
@Results(value={
	@Result(property="id", column="product_id"),
	@Result(property="name", column="product_name"),
	@Result(property="price", column="product_price"),
})
public Product select(int id);

2.3 @Insert和@SelectKey

@Insert("insert into product(product_name, product_price) values(#{name}, #{price})")
public void insert(Product product);

如果要返回插入数据的主键,可以使用@SelectKey注解。

@SelectKey的命令格式:

@SelectKey(before = true|false, 
			keyProperty = "实体属性", 
			keyColumn = "主键列",
			resultType = 映射结果的类型, 
			statement="获取主键的sql"

例如:

@Insert("insert into product(product_name, product_price) values(#{name}, #{price})")
@SelectKey(
		before = false, 
		keyProperty = "id", 
		keyColumn = "product_id",
		resultType = Integer.class, 
		statement = { "select last_insert_id()" })
public int insert(Product product);

2.4 @Update

@Update("update product set product_price = #{price} where product_id = #{id}")
public void update(Product product);

2.5 @Delete

@Delete("delete from product where product_id = #{id}")
public void delete(int id);

2.6 在注解中中定义动态sql

如果要在注解中实现动态sql,那么必须要把动态sql命令定义在script标签中。例如:

(1)根据产品名称动态添加查询条件。

@Select("<script>select * from product <if test=\"name !=null \">product_name like CONCAT('%', #{name}, '%')</if></script>")    
public List<Product> findUserByName(String name);  

(2)根据产品编号同时删除多个产品。

@Delete({
	"<script>delete from product where product_id in " +
        "<foreach collection=\"ids\" item = \"id\" open=\"(\" separator=\",\" close=\")\">" +
    	    "#{id}" +
        "</foreach>" +
    "</script>"
})
void deleteProducts(int[] ids);

三、配置映射关系

3.2 配置一对多关系

3.2.1 环境准备

例如:产品和产品类型。产品类型和产品就是典型的一对多关系。在数据库设计中,一对多的关系是通过在多的一方建立外键约束来实现的。

3.1.1.1 创建表

产品表:

create table product (
	id int primary key auto_increment comment '产品编号',
	name varchar(255) not null default '' comment '产品名称',
	price int not null default 0 comment '价格',
	cid int not null comment '类别编号'
);

产品类型表:

create table category (
	id int primary key auto_increment comment '产品类型编号',
	name varchar(255) not null default '' comment '类型名称'
);

建立外键:

alter table product 
add constraint fk_product_category foreign key(cid) references category(id);

初始化数据:

insert into category(name)
values('家电');
insert into category(name)
values('文具');

insert into product(name, price, cid)
values('洗衣机', 3999, 1);
insert into product(name, price, cid)
values('电冰箱', 1999, 1);
insert into product(name, price, cid)
values('空调机', 2999, 1);
insert into product(name, price, cid)
values('铅笔', 1, 2);
insert into product(name, price, cid)
values('记事本', 10, 2);

3.1.1.2 定义实体

(1)产品实体

public class Product {
	private Integer id;
	private String name;
	private Integer price;
	private Category category;
	
	// 省略了setters和getters方法...
	
}

(2)产品类型实体:

/*
 * 产品类型
 */
public class Category {
	private Integer id;
	private String name;
	private Set<Product> products = new HashSet<Product>(0);
	
	// 省略了setters和getters方法...

3.1.1.3 定义别名

<!-- 配置别名 -->
<typeAliases>
	<typeAlias type="com.xxx.domain.Product" alias="productAlias"/>
	<typeAlias type="com.xxx.domain.Category" alias="categoryAlias"/>
</typeAliases>

3.2.2 在配置文件中配置一对多

配置一对多关系就是在一方(产品类别)的ResultMap中使用collection节点指定要执行关联查询的sql语句。

3.2.2.1 产品类型映射文件

<?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.xxx.mapper.CategoryMapper">

	<!-- 映射结果集 -->
	<resultMap id="categoryResultMap" type="categoryAlias">
		<id property="id" column="id"/>
		<id property="name" column="name"/>
		<!-- 配置一对多的关系 
				property:集合的属性名
				ofType:集合元素的类型
				column:当前实体对应表的主键名
				select:指定关联查询的SQL语句
				fetchType: 指定是否延迟加载,lazy代表延迟加载,eager代表不延迟加载
		-->
		<collection property="products" ofType="productAlias" column="id"
			select="com.xxx.mapper.ProductMapper.selectProductByCategoryId"/>
	</resultMap>
	
	<!-- 根据ID查询产品类别 -->
	<select id="selectCategoryById" resultMap="categoryResultMap">
		select * from category where id = #{categoryId}
	</select>
	
</mapper>

因为在Category实体中包含products集合属性,该集合用于存储该类别下的产品。所以,在ResultMap中使用collection节点映射集合属性。

3.2.2.2 产品映射文件

<?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="mybatisqs.demo01helloword.ProductMapper">

	<!-- 执行一对多查询的时候使用的select语句 -->
	<select id="selectProductByCategoryId" parameterType="int" resultType="productAlias">
		select * from product where cid = #{categoryId}
	</select>
	
</mapper>

3.2.2.3 定义映射接口

(1)CategoryMapper接口

/*
 * 该接口用来映射到CategoryMapper.xml文件
 * 
 */
public interface CategoryMapper {

	/**
	 * 根据产品类别ID查询
	 * @param categoryId
	 * @return
	 */
	Category selectCategoryById(int categoryId);
	
}

(2)ProductMapper接口

/**
 * 查询指定类别的所有产品
 * @param categoryId 类别编号
 * @return
 */
List<Product> selectProductByCategoryId(int categoryId);

3.2.2.4 配置映射文件

修改mybatis-config.xml文件,配置映射文件。

<mappers>
	<mapper resource="com/xxx/mapper/ProductMapper.xml" />
	<mapper resource="com/xxx/mapper/CategoryMapper.xml" />
</mappers>

3.2.2.5 测试

public class Demo03 {
	
	private SqlSession session;
	
	// 执行单元测试前先执行该方法
	@Before
	public void init() {
		System.out.println("执行init...");
		session = MyBatisUtil.getSession();
	}
	
	// 执行完单元测试后执行该方法
	@After
	public void after() {
		System.out.println("执行after...");
		//提交事务
		session.commit();
		//关闭session
		session.close();
	}

	@Test
	public void testOneToManyQuery() {
		CategoryMapper categoryMapper = session.getMapper(CategoryMapper.class);
		Category category = categoryMapper.selectCategoryById(1);
		System.out.println(category);
	}
	
}

3.2.3 使用注解方式配置一对多

3.2.3.1 在映射接口上使用注解

(1)CategoryMapper文件

@Select("select * from category where id = #{categoryId}")
@Results({ 
     @Result(property="id", column="id"),
     @Result(property="name", column="name"),
     @Result(property="products", column="id", many=@Many(
     		select="mybatisqs.demo01helloword.ProductMapper.selectProductByCategoryId"))
 })
Category selectCategoryById(int categoryId);

(2)ProductMapper文件

@Select("select * from product where cid = #{cid}")
@Results(value={
	@Result(property="id", column="id"),
	@Result(property="name", column="name"),
	@Result(property="price", column="price")
})
List<Product> selectProductByCategoryId(int cid);

3.2.3.2 配置映射类

修改mybatis-config.xml文件,配置映射类。

<mappers>
	<mapper class="mybatisqs.demo01helloword.CategoryMapper"/>
	<mapper class="mybatisqs.demo01helloword.ProductMapper"/>
</mappers>

3.2.3.4 测试

略。

3.3 配置多对一关系

一个类型可以有多种产品,产品和类型之间就是多对一的关系。

3.3.1 在配置文件中配置多对一

配置多对一关系就是在多方(产品)的ResultMap节点中使用association节点指定关联实体(产品类型)的属性和表字段的对应关系。

3.3.1.1 产品映射文件

<resultMap id="productResultMap" type="productAlias">
	<id property="id" column="id" />
	<id property="name" column="name" />
	<id property="price" column="price" />
	<association property="category" javaType="categoryAlias">
		<result property="id" column="cid"/>
		<result property="name" column="cname"/>
	</association>
</resultMap>

<!-- 查询所有产品  -->
<select id="selectAllProducts" resultMap="productResultMap">
	select p.*, c.name as cname from product p, category c where p.cid = c.id; 
</select>

上面的association也可以这样写:

<!-- 
	通过select语句查询产品关联的类别
		property:关联实体的属性名
		javaType:关联实体的属性类型
		column: 多方的外键名
		select:执行关联查询的SQL语句
 -->
<association property="category" javaType="categoryAlias" column="cid"
			select="com.xxx.mapper.CategoryMapper.selectCategoryById"/>

3.3.1.2 产品映射接口

public interface ProductMapper {

	List<Product> selectAllProducts();
	
}

3.3.1.3 测试

@Test
public void testManyToOneQuery() {
	ProductMapper productMapper = session.getMapper(ProductMapper.class);
	List<Product> products = productMapper.selectAllProducts();
	for (Product p : products) {
		System.out.println(p);
	}
}

3.3.2 使用注解方式配置多对一

3.3.2.1 在产品映射接口上使用注解

使用注解配置多对一关系,就是在@Result中指定one属性。

@Select("select * from product")
@Results(value={
	@Result(property="id", column="id"),
	@Result(property="name", column="name"),
	@Result(property="price", column="price"),
	@Result(property="category", column="cid", 
		one=@One(select="mybatisqs.demo01helloword.CategoryMapper.selectCategoryById"))
})
List<Product> selectAllProducts();

3.3.2.2 测试

略。

3.4 配置多对多关系

3.4.1 环境准备

例如:学生和课程。学生和课程就是典型的多对多关系。在数据库设计中,多对多的关系是通过一个中间表来记录两边主键来实现的。

3.4.1.1 创建表

学生表:

create table student (
	id int primary key auto_increment comment '学生编号',
	name varchar(255) not null default '' comment '学生名字',
	gender tinyint(1) not null default 1 comment '学生性别,1代表男,2代表女',
	phone varchar(11) default '' comment '手机号码'
);

课程表:

create table course (
	id int primary key auto_increment comment '课程编号',
	name varchar(255) not null default '' comment '课程名称'
);

学生选修表:

create table student_course (
	stu_id int,
	course_id  int,
	primary key(stu_id, course_id)
);

初始化数据:

insert into student(name, gender, phone)
values('jacky', 1, '13522237843');
insert into student(name, gender, phone)
values('mickey', 1, '13622237843');
insert into student(name, gender, phone)
values('judy', 2, '13322237843');

insert into course(name)
values('外语');
insert into course(name)
values('计算机');

insert into student_course
values(1, 1);
insert into student_course
values(1, 2);
insert into student_course
values(2, 1);
insert into student_course
values(2, 2);
insert into student_course
values(3, 1);

3.4.1.2 定义实体

(1)学生实体

public class Student {
	private Integer id;
	private String name;
	private Boolean gender;
	private String phone;
	private Set<Course> courses = new HashSet<Course>(0);

	// 省略了setters和getters方法..
}

(2)课程实体

public class Course {
	private Integer id;
	private String name;
	private Set<Student> students = new HashSet<Student>(0);
	
	// 省略了setters和getters方法..
}

3.4.1.3 定义别名

<!-- 配置别名 -->
<typeAliases>
	<typeAlias type="com.xxx.domain.Student" alias="studentAlias"/>
	<typeAlias type="com.xxx.domain.Course" alias="courseAlias"/>
</typeAliases>

3.4.2 在配置文件中配置多对多关系

3.4.2.1 创建学生映射文件

<?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="mybatisqs.demo02mangtomany.StudentMapper">

	<resultMap id="studentResultMap" type="studentAlias">
		<id property="id" column="id" />
		<id property="name" column="name" />
		<id property="gender" column="gender" />
		<id property="phone" column="phone" />
		<!-- 多表关联映射 -->
		<collection property="courses" ofType="courseAlias">
			<id property="id" column="cid"/>
			<result property="name" column="cname"/>
		</collection>
	</resultMap>
	
	<!-- 查询所有学生  -->
	<select id="selectAllStudents" resultMap="studentResultMap">
		select s.*, c.id as cid, c.name as cname from student s, course c, student_course sc 
		where s.id = sc.stu_id and c.id = sc.course_id; 
	</select>

</mapper>

3.4.2.2 创建映射接口

public interface StudentMapper {

	List<Student> selectAllStudents();
	
}

3.4.2.3 配置映射文件

修改mybatis-config.xml文件,配置映射文件。

<mappers>
	<mapper resource="mybatisqs/demo02mangtomany/StudentMapper.xml"/>
</mappers>

3.2.2.5 测试

public class Demo02 {
   private SqlSession session;

   // 执行单元测试前先执行该方法
   @Before
   public void init() {
   	System.out.println("执行init...");
   	session = MyBatisUtil.getSession();
   }

   // 执行完单元测试后执行该方法
   @After
   public void after() {
   	System.out.println("执行after...");
   	// 提交事务
   	session.commit();
   	// 关闭session
   	session.close();
   }

   @Test
   public void testManyToManyQuery() {
   	StudentMapper studentMapper = session.getMapper(StudentMapper.class);
   	List<Student> students = studentMapper.selectAllStudents();
   	for (Student student : students) {
   		System.out.println(student);
   	}
   }

}

同样道理,如果要查询课程信息以及该选修该课程的学生,也可以参考上面方式在课程映射文件中进行配置。这里不再进行累述。

3.4.3 使用注解配置多对多关系

3.4.3.1 在映射接口中使用注解

(1)StudentMapper文件

@Select("select * from student")
@Results({ 
    @Result(property="id", column="id"),
    @Result(property="name", column="name"),
    @Result(property="gender", column="gender"),
    @Result(property="phone", column="phone"),
    @Result(property="courses", column="id", many=@Many(
    		select="mybatisqs.demo02mangtomany.CourseMapper.selectStudentCourses"))
})
List<Student> selectAllStudents();

(2)CourseMapper文件

public interface CourseMapper {
	
@Select("select c.* from course c, student_course sc where c.id = sc.course_id and sc.stu_id = #{studentId}")
List<Course> selectStudentCourses(int studentId);
	
}

3.4.3.2 配置映射接口

修改mybatis-config.xml文件,配置映射接口。

<mappers>
	<mapper class="mybatisqs.demo02mangtomany.StudentMapper"/>
	<mapper class="mybatisqs.demo02mangtomany.CourseMapper"/>
</mappers>

3.4.3.3 测试

略。

四、整合Log4j

Log4J是一种基于Java的日志输出工具。如果要查看MyBatis的执行过程,就可以在MyBatis中整合Log4J。

在MyBatis中配置Log4J

第一步:把log4j的jar包拷贝到工程中;
在mybatis安装目录下有个lib目录,该目录存储了mybatis依赖的第三方工具包。
在这里插入图片描述
第二步:在工程src目录下新建一个文本文件,并命名为log4j.properties,然后把下面内容拷贝到文件中即可;

log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n

完成上面步骤后,就可以通过log4j查看mybatis的执行过程。

五、延迟加载策略

5.1 概述

延迟加载也称为“按需加载”。在执行关联查询时候,mybatis不会把对象的关联实体查询出来,只有在实际使用到关联实体的时候,才会把关联实体查询出来。因此,延迟加载可以减少不必要的关联查询,提高数据库的查询效率。

一般来说,延迟加载在一对多或多对多关系中使用较多。

5.2 配置延迟加载

首先,把mybatis安装目录下的asm-7.0.jar和cglib-3.2.10.jar文件拷贝到项目中;
在这里插入图片描述
接着,按照下面方式配置延迟加载。

  • 方式一:局部延迟加载。

局部延迟策略就是只对某个实体类启用延迟加载策略。可以在association和one节点中指定fetchType="lazy"属性即可。

<resultMap id="categoryResultMap" type="categoryAlias">
	<id property="id" column="id" />
	<id property="name" column="name" />
	<!-- 配置一对多的关系 
		property:集合的属性名 
		ofType:集合元素的类型 
		column:当前实体对应表的主键名 
		select:指定关联查询的SQL语句 
		fetchType: 指定是否延迟加载,lazy代表延迟加载,eager代表不延迟加载 -->
	<collection property="products" ofType="productAlias" column="id" 
		select="mybatisqs.demo01helloword.ProductMapper.selectProductByCategoryId" 
		fetchType="lazy"/>
</resultMap>

如果是使用注解配置方式,可以在@Many注解中指定fetchType=FetchType.LAZY属性即可。例如:

@Select("select * from category where id = #{categoryId}")
@Results({ 
    @Result(property="id", column="id"),
    @Result(property="name", column="name"),
    @Result(property="products", column="id", many=@Many(
    		select="mybatisqs.demo01helloword.ProductMapper.selectProductByCategoryId"
    		, fetchType=FetchType.LAZY))
})
Category selectCategoryById(int categoryId);
  • 方式二:全局延迟加载

启用全局延迟加载策略后,所有实体类都会启用生效。启用全局延迟策略需要在MyBatis核心配置文件中进行配置。

<settings>
	<setting name="lazyLoadingEnabled" value="true" />
	<setting name="aggressiveLazyLoading" value="false"/>
</settings>

六、MyBatis缓存机制

6.1 缓存概述

使用缓存的最大好处可以提供数据的查询速度,减轻数据压力,提高数据库性能。

不带缓存的数据库查询:
在这里插入图片描述

带缓存的数据库查询:
在这里插入图片描述
查询带缓存数据库的时候,每次查询都会先从缓存查询数据,如果缓存中找到,那么就直接把查询到的数据返回给用户即可。如果缓存中没有找到数据,那么就会从数据库中查找。如果数据库中找到就把数据返回给用户,并且把查询到的数据保存在缓存中。下一次用户查询的时候就可以直接从缓存中查询即可。

6.2 一级缓存

一级缓存也称为Session缓存。同一个Session中的数据会保存在Session中。只要Session不关闭,不管查询N次都会返回相同的结果。

@Test
public void testQueryBuffer() {
	ProductMapper productMapper = session.getMapper(ProductMapper.class);
	Product p1 = productMapper.selectProduct(1);
	Product p2 = productMapper.selectProduct(1);
	System.out.println("是同一个对象吗?" + (p1 == p2));
}

运行上面程序,控制台输出true。

MyBatis默认已经开启的一级缓存。如果不希望使用缓存,可以执行完查询后调用session的clearCache方法清除缓存信息。

session.clearCache();

另外,如果程序在DML操作后执行了commit操作,session缓存数据也会被清空。

6.3 二级缓存

6.3.1 概述

Mybatis里面,二级缓存就是文件级别的缓存。启用二级缓存后,即使Session关闭了,也不会对缓存数据有影响。

  • MyBatis缓存的执行过程:
    如果配置二级缓存,那么执行查询操作时候,mybatis会先从二级缓存中查询数据,如果二级缓存没有,再从一级缓存(session)中查找数据,如果一级缓存也没有,才会查询数据库。
    在这里插入图片描述
    二级缓存的技术:MemCached、OSCache、EhCache等等,下面以EhCache为例介绍在mybatis中使用二级缓存。

关于EhCache的详解介绍,可以参考官方网站:http://www.mybatis.org/ehcache-cache/

6.3.2 MyBatis整合ehcache

第一步:下载和导入ehcache的jar包;
下载地址:https://github.com/mybatis/ehcache-cache/releases
在这里插入图片描述

第二步:在工程src目录下新建一个xml格式文件,该文件的名字为ehcache.xml,然后把下面内容拷贝到文件中;

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
	<!--缓存目录  -->
	<diskStore path="d:/ehcache" />
	<!--
		属性说明: 
			name: Cache的唯一标识
			maxElementsInMemory: 内存中最大缓存对象数
			maxElementsOnDisk: 磁盘中最大缓存对象数,若是0表示无穷大
			eternal: Element是否永久有效,一但设置了,timeout将不起作用
			overflowToDisk: 当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中
			timeToIdleSeconds: 设置Element在失效前允许的闲置时间。仅当element不是永久有效时使用
			timeToLiveSeconds: 设置Element在失效前允许存活时间。最大时间介于创建时间和失效时间之间。仅当element不是永久有效时使用
			diskExpiryThreadIntervalSeconds: 磁盘失效线程运行时间间隔,默认是120秒
			memoryStoreEvictionPolicy: 当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU
	 -->
	<defaultCache
		name="defaultCache"
		maxElementsInMemory="1000"
		maxElementsOnDisk="10000000"
		eternal="true"
		overflowToDisk="true"
		timeToIdleSeconds="120"
		timeToLiveSeconds="120"
		diskExpiryThreadIntervalSeconds="120"
		memoryStoreEvictionPolicy="LRU">
	</defaultCache>
</ehcache>

第三步:在需要使用缓存的映射文件中加入cache节点。

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

加入了cache后,该映射文件下的所有查询操作都会使用缓存。如果不需要启用缓存,可以在statement中指定useCache="false"属性即可。
在这里插入图片描述
值得注意的是,缓存结果的对象需要实现Serializable接口,也就是必须是可序列化的。

第四步:测试。

@Test
public void testCache() {
	StudentMapper studentMapper = session.getMapper(StudentMapper.class);
	Student s1 = studentMapper.selectStudentById(1);
	session.close();
	studentMapper = MyBatisUtil.getSession().getMapper(StudentMapper.class);
	Student s2 = studentMapper.selectStudentById(1);
	System.out.println("是同一个对象吗?" + (s1 == s2));
}

运行上面程序可以看到,控制台输出true,代表s1和s2是同一个对象。

值得注意的是,第一次查询后需要手动关闭session,这样才会写入缓存文件。

关于缓存更详细介绍,可以参考这篇文章 https://blog.51cto.com/zero01/2103911

七、MyBatis事务管理机制

MyBatis的事务管理分为两种形式:

  • 使用JDBC事务管理机制,即使用java.sql.Connection对象完成事物的提交、回滚、关闭等操作;
  • 使用MANAGED的事务管理机制。在这种机制下,MyBatis自己不会实现事务管理,而是让程序的容器来实现对事务的管理;

如何配置事务管理?
在MyBatis配置文件的enviorment节点中进行配置。例如:

<transactionManager type="jdbc"/>

enviorment节点用于配置数据库的相关信息,它的子节点transcationManager用于指定使用的事务管理机制。

一般来说,如果只是单独使用mybatis来构建本地程序,可以将事务管理设置为JDBC。但是,如果使用mybatis构建WEB应用,我们可以将事务管理设置为MANAGED,即MyBatis自己不管理事务,而是由容器负责管理事务。

发布了111 篇原创文章 · 获赞 41 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/zhongliwen1981/article/details/98595711