Mybatis---一对一关联表查询
2016-02-25 14:20
465 查看
开发过程中表的关联查询几乎处处可见,Mybatis对关联查询可进行很好的处理,下面主要记录下一对一关联表的查询。
此处用到两个实体类及其关系如下:
School与President为一对一关联,设计javaBean:
我们若想根据School的id查询scool的包含president的信息有两种方法:
Method1:关联查询
在sql中可通过如下的sql语句查询:
mybatis中第一种解决方法就是基于这种直接关联查询的思想:先把结果查询,然后利用ResultMap映射进行JavaBean的生成
此方法对应的mapper配置:
貌似很完美的解决了问题,实际上对于一般的情况这种方法是适用的。
下面提一种非同一般的情况,如果两个关联表中含有字段名相同的字段咋办?比如如果president1和school1中p_name 和s_name都改成name,为了模拟这种情况,也懒得再建新的数据表,我们通过查询结果起别名的方法,mapper配置:
运行时异常
放回null值
返回结果,输出:School [id=1, name=上海大学, president=President [id=1, name=lily]]
返回结果,输出:School [id=1, name=上海大学, president=President [id=1, name=上海大学]]
实际的测试结果如下:
mybatis很诡异的把president的name信息搞成了school的name,因为在resultmap中有两个相同的映射关系school自身的name映射和president的name映射,针对sql查询结果,测试表明,如果查询结果中有多个name,即使它们的值不同,mybatis只会将第一个name的值取出注入到映射关系对应的实体类属性中。
难道就没有方法解决这种情况?当然有,这时就要引出第二种关联查询方法。
Method2:嵌套查询
我们可以通过下面的方法进行人工拼接要查询的结果,比如要查询id为1的school信息,首先我们先只查询学校的信息:
然后根据查询的学校信息中的president_id去president1表中查询president的信息:
最后我们自己根据两次查询的结果手动拼接成最终结果即可。
mybatis嵌套查询的思想与上面讲的思想类似,先看一下该方法的mapper配置:
这次真的完美的解决了关联表查询的情况
测试源码下载
此处用到两个实体类及其关系如下:
School与President为一对一关联,设计javaBean:
//校长 public class President { private int id; private String name; @Override public String toString() { return "President [id=" + id + ", name=" + name + "]"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }和
public class School { private int id; private String name; private President president; @Override public String toString() { return "School [id=" + id + ", name=" + name + ", president=" + president + "]"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public President getPresident() { return president; } public void setPresident(President president) { this.president = president; } }创建数据表:
create table president1( p_id int not null auto_increment primary key, p_name varchar(50) not null ); insert into president1(p_name) values('lily'),('Tom'); create table school1( s_id int not null auto_increment primary key, s_name varchar(50) not null, president_id int not null, constraint foreign key(president_id) references president1(p_id) ); insert into school1(s_name,president_id) values('上海大学',1),('复旦大学',2);
我们若想根据School的id查询scool的包含president的信息有两种方法:
Method1:关联查询
在sql中可通过如下的sql语句查询:
select * from president1 p,school1 s where p.p_id=s.president_id and s.s_id=1;查询结果:
mybatis中第一种解决方法就是基于这种直接关联查询的思想:先把结果查询,然后利用ResultMap映射进行JavaBean的生成
此方法对应的mapper配置:
<!-- 根据id获得包含校长信息的学校信息 --> <select id="getSchool1" resultMap="getSchool1Map"> select * from president1 p,school1 s where p.p_id=s.president_id and s.s_id=#{#} </select> <resultMap type="School" id="getSchool1Map"> <id column="s_id" property="id"/> <result column="s_name" property="name"/> <association property="president" javaType="President"> <id column="p_id" property="id"/> <result column="p_name" property="name"/> </association> </resultMap><!-- 根据id获得包含校长信息的学校信息 --> <select id="getSchool1" resultMap="getSchool1Map"> select * from president1 p,school1 s where p.p_id=s.president_id and s.s_id=#{id} </select> <resultMap type="School" id="getSchool1Map"> <id column="s_id" property="id"/> <result column="s_name" property="name"/> <association property="president" javaType="President"> <id column="p_id" property="id"/> <result column="p_name" property="name"/> </association> </resultMap>看上去与单表查询没什么不同?那就错了,需要注意到association标签,mybatis官方文档对该标签的解释为:一个复杂的类型关联;许多结果将包成这种类型。也就是说我们可以通过它把查询结果中的部分结果包装成一个javabean,上面的配置我们把(p_id,p_name)封装如President中,看一下此时的测试结果:
貌似很完美的解决了问题,实际上对于一般的情况这种方法是适用的。
下面提一种非同一般的情况,如果两个关联表中含有字段名相同的字段咋办?比如如果president1和school1中p_name 和s_name都改成name,为了模拟这种情况,也懒得再建新的数据表,我们通过查询结果起别名的方法,mapper配置:
<!-- 根据id获得包含校长信息的学校信息 --> <select id="getSchool2" resultMap="getSchool2Map"> select s_id,s_name name,p_id,p_name name from president1 p,school1 s where p.p_id=s.president_id and s.s_id=#{id} </select> <resultMap type="School" id="getSchool2Map"> <id column="s_id" property="id"/> <result column="name" property="name"/> <association property="president" javaType="President"> <id column="p_id" property="id"/> <result column="name" property="name"/> </association> </resultMap>java测试代码:
public void testGetSchoolById2(){ SqlSessionFactory sessionFactory = DbUtils.getSqlFactory(); SqlSession session = sessionFactory.openSession(); String statement = "com.cjc.mapper.schoolMapper."; School s1 = session.selectOne(statement+"getSchool2", 1); System.out.println(s1); session.close(); }可以猜测下测试的结果,无非有下面几种:
运行时异常
放回null值
返回结果,输出:School [id=1, name=上海大学, president=President [id=1, name=lily]]
返回结果,输出:School [id=1, name=上海大学, president=President [id=1, name=上海大学]]
实际的测试结果如下:
mybatis很诡异的把president的name信息搞成了school的name,因为在resultmap中有两个相同的映射关系school自身的name映射和president的name映射,针对sql查询结果,测试表明,如果查询结果中有多个name,即使它们的值不同,mybatis只会将第一个name的值取出注入到映射关系对应的实体类属性中。
难道就没有方法解决这种情况?当然有,这时就要引出第二种关联查询方法。
Method2:嵌套查询
我们可以通过下面的方法进行人工拼接要查询的结果,比如要查询id为1的school信息,首先我们先只查询学校的信息:
然后根据查询的学校信息中的president_id去president1表中查询president的信息:
最后我们自己根据两次查询的结果手动拼接成最终结果即可。
mybatis嵌套查询的思想与上面讲的思想类似,先看一下该方法的mapper配置:
<select id="getSchool3" resultMap="getSchool3Map"> <span style="white-space:pre"> </span>select * from school1 where s_id=#{id} </select> <resultMap type="School" id="getSchool3Map"> <span style="white-space:pre"> </span><id column="s_id" property="id"/> <span style="white-space:pre"> </span><result column="s_name" property="name"/> <span style="white-space:pre"> </span><!-- 此处不是使用resultMap的形式,而是将getPresident查询的结果嵌入进来, <span style="white-space:pre"> </span>column="president_id"的使用是为了将该school中的president_id信息传入查询:getPresident中--> <span style="white-space:pre"> </span><association property="president" column="president_id" select="getPresident" /> </resultMap> <!-- 根据p_id查询president的信息 --> <select id="getPresident" resultType="President"> <span style="white-space:pre"> </span>select p_id id,p_name name from president1 where p_id=#{id} </select>此过程相当于执行了两次查询,因为在每次查询为都对结果进行了封装,所以即使两个表有相同的字段名,最后的实体类的结果信息也不会有method1中的情况,查询结果:
这次真的完美的解决了关联表查询的情况
测试源码下载
相关文章推荐
- 深入浅析mybatis oracle BLOB类型字段保存与读取
- MyBatis MapperProvider MessageFormat拼接批量SQL语句执行报错的原因分析及解决办法
- oracle+mybatis 使用动态Sql当插入字段不确定的情况下实现批量insert
- 浅析Mybatis 在CS程序中的应用
- Java Mybatis框架入门基础教程
- Java简单实现SpringMVC+MyBatis分页插件
- MyBatis批量添加、修改和删除
- MyBatis与Hibernate的比较
- 浅析mybatis和spring整合的实现过程
- mybatis的动态sql详解(精)
- Mybatis实现增删改查及分页查询的方法
- MyBatis入门学习教程(一)-MyBatis快速入门
- Spring与Mybatis的整合方法有哪些
- 详解MyBatis直接执行SQL查询及数据批量插入
- 解决springmvc+mybatis+mysql中文乱码问题
- Spring3.1.1+MyBatis3.1.1的增、删、查、改以及分页和事务管理
- Spring+Mybatis+Mysql搭建分布式数据库访问框架的方法
- Mybatis实战教程之入门到精通(经典)
- Mybatis与Hibernate的区别
- SpringMVC+MyBatis项目总结(一)