高级映射
通过定义resultMap来实现结果集自动封装到指定对象并返回结果的一种映射方式
resultMap:
- 属性:
- type:类型名称
- id:resultMap的唯一标识
- 节点:
- id:主键列,可设可不设 但可能影响查询效率
- column:sql结果集中返回的列名
- property:将要映射到的类中的属性名称
- result:普通列,
- 属性与主键列相同
- association:用于一对一关系映射,
- id,属性与主键列相同
- result,属性与主键列相同
- select
- property
- column
- collection:用于一对多关系映射,
- id,属性与主键列相同
- result,属性与主键列相同
- ofType:对应的目标类型(不能使用javaType,否则无法以List的形式调用setter方法)
- id:主键列,可设可不设 但可能影响查询效率
延迟加载
也称为懒加载,在查询时先加载主信息,在需要时才查询从信息。实现懒加载有以下三点需要注意:
- 在MyBatis中,resultMap标签的association标签和collection标签具有延迟加载的功能。
- 在SqlMapConfig.xml中配置setting标签
- 使用嵌套的select语句不当时会造成N+1问题----每个查询跟着一个查询,即一条数据要连续访问两次数据库。因此不建议使用嵌套的select语句
<settings>
<!-- 开启延迟加载,默认值为true -->
<setting name="lazyLoadingEnabled" value="true"></setting>
<!-- 设置积极懒加载,默认为true,设置为false之后则不会立即加载从数据 -->
<setting name="aggressiveLazyLoading" value="false"></setting>
</settings>
mapper文件使用嵌套查询
//省略外层的resultMap标签
<association property="user" select="com.mapper.UserMapper.findUserById" column="user_id"><association>
association
- select属性:指定关联查询的查询语句(前提是需要存在这条对应的statement),然后将查询结果封装到property属性指定的变量中
- column属性:传入statement的变量值,如果只有一个参数则直接传指定列所查询出的结果;如果有多个参数需按{col1=prop1,col2=prop2}的形式传入。 SqlMapConfig.xml对应的setting:
collection
查询缓存
一级缓存:
- 存在于SqlSession中,在SqlSession中有一个数据区域,是Map结构,这个区域就是一级缓存,以及缓存中key为sql语句、条件、statement等信息组成的唯一值,value为查询出的结果对象
- 默认查询开启,修改关闭
- 当执行了修改数据操作(commit)时会清空缓存
二级缓存:
- 存在于namespace下的mapper中,在namespace中有一个数据区域,也是Map结构
- 默认关闭,需要手动开启
- 需要开启总开关(在SqlMapConfig.xml中),且在mapper文件中也需启用配置
总结:
- 对于访问响应速度要求极高的,但是实时性不高的查询可以使用二级缓存技术,注意在使用二级缓存的时候要设置一下自动刷新的间隔(cache标签中有一个flashInterval属性)来定时刷新二级缓存,这个刷新间隔根据具体需求来设置,比如设置30分钟、60分钟等,单位为毫秒)
- 二级缓存对细粒度的数据,缓存实现较差。当访问量较大 又需要每次查询都是最新数据时无法实现只刷新指定记录的信息而不刷新其他记录的信息,因为二级缓存是mapper级别的,当想要刷新一条记录的缓存时,所有记录的缓存都将被清空
Spring和MyBatis整合
整合思路:
- 数据源交由Spring管理
- SqlSessionFactory交由Spring进行单例管理
- 由Spring管理原始Dao的实现类或者mapper代理类
整合步骤:
- 导包
- Mybatis的SqlMapConfig配置文件不需要再配置数据源,只需要加载mapper配置文件即可(如无需进行其他设置项)
- 完成mapper类编写,完成mapper配置文件,完成数据库配置文件
- 在Spring配置文件中配置数据源,加载SqlMapConfig配置文件,加载mapper类
- 完成测试类编写
代码实现:
- MyBatis配置文件SqlMapConfig.xml
<?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>
<mappers>
<mapper resource="com/ms/mapper/UserMapper.xml" />
</mappers>
</configuration>
- Mapper配置文件UserMapper.xml
<?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.ms.mapper.UserMapper">
<select id="findUserById" parameterType="int" resultType="com.ms.domain.User">
SELECT * FROM user WHERE id=#{id}
</select>
</mapper>
- Spring配置文件application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:property-placeholder location="db.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
<property name="maxActive" value="10" />
<property name="maxIdle" value="5" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="mybatis/SqlMapConfig.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 单个mapper配置 -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.ms.mapper.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<!-- 批量一个包配置 -->
<!-- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ms.mapper" />
已经默认配置了sqlSessionFactory 但只有一个sqlSessionFactory时
</bean> -->
</beans>
- UserMapper.java
package com.ms.mapper;
import com.ms.domain.User;
public interface UserMapper {
public User findUserById(int id);
}
- 测试代码
package com.ms.test;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.ms.domain.User;
import com.ms.mapper.UserMapper;
public class TestUserMapper {
ApplicationContext applicationContext;
@Before
public void setUp() {
applicationContext = new ClassPathXmlApplicationContext("spring/applicationContext.xml");
}
@Test
public void findUserById() {
UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");
User user = userMapper.findUserById(1);
System.out.println(user);
}
}