MyBatis的关联映射
目录
原始的jdbc在查询数据时,要查询多个表的数据,一种做法是:一个表的写一个sql,用该表的实体类去装载数据,最后查出来用java组装起来,另一种做法:写一个综合实体类(把要查的字段对应的属性都加进去),写一个sql,一次性查出来。那么我们的MyBatis持久化框架对待这种问题时如何处理的,有没有简单的方法。我们今天就来学习MyBatis的关联映射
关联映射的优点:便于查询相关表信息。
对象之间建立联系,需要用到关联属性,关联属性一般有两种类型:集合对象类型,单个对象类型。
接下来我们看看到底是怎么做的?
今天我们要做的是在前面的文章说的搭好MyBaits项目的基础上,可以看MyBatis的映射器规则、MyBatis的动态sql这两篇文章中任何一篇文章中搭建的MyBatis项目的基础上做今天的练习都可以。
之前的项目名称是:mybatis_demo1、数据库类型:mysql、数据库名称:jsd15077db、用的表有user, record表。
两张表的信息如下:
user(id,username、pwd、name、gender),各字段分别是用户id(主键)、登录名称、密码、昵称、性别。
record(record_id、user_id、remark、status),各字段分别是记录id(主键)、用户id(外键)、备注、状态。
实例一:关联属性是集合
场景,根据用户id我们查询用户信息时同时也要查出这个用户的所有记录,一个用户有多条记录。
1.单独发送一个sql抓取数据给关联属性
(1).添加关联属性
给用户实体类添加关联属性records,并且同时添加get、set方法,如下图:
(2).编写sql
在UserMapper.xml文件中添加这个用于关联查询的sql,id为linkQuery,代码如下:
注:
sql中,resultType属性是按照属性名称匹配的,匹配不上就为空。而resultMap是开发者自己定义的匹配规则,在<resultMap>标签中:
要自定义的关联属性如果是集合就用<collection>标签,如果不是就用<association>标签;
ofType指的是该集合元素的类型;
select指的是另一个查询;
column指的是该集合的元素的某个属性作为另一个查询的参数。
(3).接口中添加对应方法
在UserDao接口中添加方法linkQuery,代码如下图:
(4).测试
在com.cdd.test包下新建类TestAssicoation用于测试,代码如下:
package com.cdd.test;
import org.apache.ibatis.session.SqlSession;
import com.cdd.dao.UserDao;
import com.cdd.entity.Record;
import com.cdd.entity.User;
import com.cdd.util.MyBatisUtil;
public class TestAssication {
public static void main(String[] args) throws Exception{
SqlSession session = MyBatisUtil.getSqlSession();
UserDao dao = session.getMapper(UserDao.class);
User user = dao.linkQuery(3);
System.out.println(user.getUsername()+"的记录有:");
for(Record r : user.getRecords()){
System.out.println(r);
}
session.close();
}
}
查看控制台输出:
2.主对象数据和关联属性一起抓取。
将关联数据与主对象数据一起抓取(基于表关联查询join..on...).适用于关联多个表。
(1).编写sql
在UserMapper.xml文件中,添加查询sql,id为linkSerach,代码如下:
(2).测试
在TestAssication类中编写测试,把上一个的测试部分先注释,代码如下:
查看控制台:
注:在<resultMap>标签中,属性与对应时,如果是表主键就用<id>标签,不是的话就用<result>标签
实例二:关联属性是对象
查询所有的记录信息,把对应的用户信息装载到记录实体类中。
1.添加关联属性
在记录实体类Record类中添加关联属性user,并且添加get、set方法,情况如下:
2.编写接口
在RecordMapper.xml文件中编写查询sql,id为linkFind,代码如下:
3.编写接口
在RecordDao接口中,添加方法linkSerach方法,代码如下:
4.测试
在TestAssication中先注释之前的测试部分,再编写现在的测试,情况如下:
package com.cdd.test;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import com.cdd.dao.RecordDao;
import com.cdd.dao.UserDao;
import com.cdd.entity.Record;
import com.cdd.entity.User;
import com.cdd.util.MyBatisUtil;
public class TestAssication {
public static void main(String[] args) throws Exception{
SqlSession session = MyBatisUtil.getSqlSession();
UserDao dao = session.getMapper(UserDao.class);
// User user = dao.linkQuery(3);
// System.out.println(user.getUsername()+"的记录有:");
// for(Record r : user.getRecords()){
// System.out.println(r);
// }
// User user1 = dao.linkSerach(4);
// System.out.println(user1.getUsername()+"的记录有:");
// for(Record r : user1.getRecords()){
// System.out.println(r);
// }
RecordDao dao1 = session.getMapper(RecordDao.class);
List<Record> recordList = dao1.linkFind();
for(Record r : recordList){
System.out.println(r);
}
session.close();
}
}
查看控制台输出:
实例三:MyBatis返回自动主键
在实际情况中,我们往往保存一个新对象,而这个对象对应的数据表的主键是自增长,mybatis在保存一条记录时是如何获取到这条记录自动产生的主键的。我们现在来看看。
场景,现在要保存一个用户到User表中,User表的主键id,是自增长的,可以先看看这个表的结构:
1.编写sql
在UserMapper.xml文件中编写保存用户的sql,id为save,代码如下:
注:
useGenerateKeys="true",不用写查询语句,能够降低数据库压力,可以得到刚才保存的那条记录的主键id,使用于mysql 数据库。
keyProperty="id" ,id为User表的主键。
2.编写接口
在UserDao中添加对应方法save,代码如下:
3.测试
在TestAssication类中先注释掉之前的测试部分,添加对保存用户的测试,代码如下:
执行,查看控制台:
再看数据库:
附加:
如果我们的数据库是Oralce怎么写呢?请往下看。
注:
keyProperty="id" ,要查询的字段是id;
order="BEFORE" ,在insert之前执行,还有AFTER是在之后(都用大写)
到这里MyBatis的关联映射部分,就暂告一段落了。有什么问题请大家多多指教!