新建SQL映射文件lock.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.citi.dao.LockDao"> <select id="getLockById" resultMap="mylock"> SELECT l.id,l.lockName,k.id kid, k.keyname,k.lockid FROM t_lock l LEFT JOIN t_key k ON l.id = k.lockid WHERE l.id=#{id} </select> <resultMap id="mylock" type="com.citi.entity.Lock"> <id property="id" column="id"></id> <result property="lockName" column="lockName"></result> <collection property="keyList" ofType="com.citi.entity.Key"> <!--column是起的别名,如果没起别名,就和数据库列字段一致--> <id property="id" column="kid"></id> <result property="keyName" column="keyName"></result> </collection> </resultMap> </mapper> 复制代码
- collection:复杂类型的集合
- ofType:指定集合里面元素的类型
将lock.xml注册到MyBatis全局配置文件中
<mappers> <mapper resource="mappers/employee.xml"/> <mapper resource="mappers/cat.xml"/> <mapper resource="mappers/key.xml"/> <mapper resource="mappers/lock.xml"/> </mappers> 复制代码
新建测试类
public class LockDaoTest { SqlSessionFactory sqlSessionFactory = null; SqlSession openSession = null; @Before public void setUp() throws Exception { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); openSession = sqlSessionFactory.openSession(); } @Test public void getLockById() { LockDao lockDao = openSession.getMapper(LockDao.class); Lock lock = lockDao.getLockById(3); System.out.println(lock); List<Key> keyList = lock.getKeyList(); for (Key key : keyList) { System.out.println("Key:" + key); } } } 复制代码
执行测试
联合查询较为繁琐,使用分步查询也可以完成;先查出Key,在根据Key的信息到t_lock表中查出锁的信息
分步查询 Key -> Lock
在KeyDao和LockDao中分别增加一个查询方法
Lock getLockByIdSimplely(Integer id); 复制代码
Key getKeyByIdSimplely(Integer id); 复制代码
在lock.xml映射文件中增加SQL语句
<select id="getLockByIdSimplely" resultType="com.citi.entity.Cat"> select * from t_lock where id = #{id} </select> 复制代码
在key.xml中完成分步查询
<select id="getKeyByIdSimplely" resultMap="mykeysimplely"> select * from t_key where id = #{id} </select> <resultMap id="mykeysimplely" type="com.citi.entity.Key"> <id property="id" column="id"></id> <result property="keyName" column="keyname"></result> <association property="lock" select="com.citi.dao.LockDao.getLockByIdSimplely" column="lockid"> </association> </resultMap> 复制代码
- property:指定封装哪个属性
- select:指定一个查询SQL的唯一标识,MyBatis自动调用指定的SQL将查询的结果结果封装到指定的属性
- colume:指定将哪一列数据传递过去
在KeyDaoTest中增加getKeyByIdSimplely方法的测试代码
@Test public void getKeyByIdSimplely() { KeyDao keyDao = openSession.getMapper(KeyDao.class); Key key = keyDao.getKeyByIdSimplely(1); System.out.println(key); } 复制代码
执行测试
根据控制台打印的信息可以看出分步查询其实就是分别执行了两条SQL,先获取Key,在获取Lock;每次查询Key都要数据库执行两条SQL严重影响性能,而且并不是每次查询Key的时候也需要锁的信息,因此对查询锁信息可以使用按需加载,需要的时候再执行查锁。
在MyBatis全局配置文件中配置开启延迟加载和属性按需加载
<settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="true"/> </settings> 复制代码
将打印key的代码注释(不注释会调用Key的toString方法导致懒加载失效),再次执行测试
控制台只会打印出一条SQL语句,也就是后台只执行了一条SQL语句
修改测试代码,获取Lock
@Test public void getKeyByIdSimplely() { KeyDao keyDao = openSession.getMapper(KeyDao.class); Key key = keyDao.getKeyByIdSimplely(1); // System.out.println(key); String lockName = key.getLock().getLockName(); System.out.println(lockName); } 复制代码
再次测试
覆盖全局的延迟加载配置,在association标签中增加fetchType="eager",注释掉获取锁的代码,再次执行测试
分步查询 Lock -> Key
分别在LockDao、KeyDao中新增方法
Lock getLockByIdStep(Integer id); 复制代码
List<Key> getKeysByLockId(Integer id); 复制代码
在key.xml中新增查询key的SQL语句
<select id="getKeysByLockId" resultType="com.citi.entity.Key"> select * from t_key where lockid = #{id} </select> 复制代码
在lock.xml中新增getLockByIdStep方法的映射
<select id="getLockByIdStep" resultMap="mylockstep"> select * from t_lock where id = #{id} </select> <resultMap id="mylockstep" type="com.citi.entity.Lock"> <id property="id" column="id"></id> <result property="lockName" column="lockName"></result> <collection property="keyList" select="com.citi.dao.KeyDao.getKeysByLockId" column="id"> </collection> </resultMap> 复制代码
增加测试方法
@Test public void getLockByIdStep() { LockDao lockDao = openSession.getMapper(LockDao.class); Lock lock = lockDao.getLockByIdStep(3); System.out.println(lock); List<Key> keyList = lock.getKeyList(); for (Key key : keyList) { System.out.println("Key:" + key); } } 复制代码
执行测试
reslutMap标签中的 column属性是用来传递select属性指定的查询方法的参数,如果该查询方法有多个参数则可以使用{key1=value1,key2=value2}的方式来传递数据。
实际应用中更推荐使用连接查询的方式而非分步查询,相比较会减少对数据库的压力