方式1(嵌套查询):
在本类的mapper映射配置文件中的ResultMap标签中使用association子标签,对关联对象的属性进行关联
例如:User中关联Department(多对一)
----------User的mapper映射配置文件---------<?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.tabchanj.mybatis.domain.UserMapper"> <resultMap type="com.tabchanj.mybatis.domain.User" id="User"> <!-- property:表示本类中关联的对象属性 dept_id:表示本类的表中哪一列的值将传入select语句中作为参数进行查询 select:表示查询出关联对象的语句,, 其格式为该关联对象的类所配置的mapper映射文件的sql语句地址,为其文件中的namespace+sql语句的id --> <association property="dept" column="dept_id" select="com.tabchanj.mybatis.domain.DepartmentMapper.get" /> </resultMap> <select id="get" parameterType="Long" resultMap="User"> select * from t_user where id = #{id} </select> <select id="list" resultMap="User"> select * from t_user </select> </mapper>
-----------Department的mapper映射配置文件----------<?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.tabchanj.mybatis.domain.DepartmentMapper"> <resultMap type="Department" id="DepartmentMap"/> <select id="get" parameterType="Long" resultMap="DepartmentMap"> select * from t_department where id = #{id} </select> <select id="list" resultMap="DepartmentMap"> select * from t_department </select> </mapper>
//--------测试类----------- @Test public void testName1() throws Exception { //通过sqlsession获得代理对象(Mapper) UserMapper mapper = MyBatisUtil.openSession().getMapper(UserMapper.class); //mapper调用接口中方法,相当于执行了mapper映射文件中的id为get的sql语句 User u = mapper.get(1L); }
---------结果发出了2条sql,即在未使用department的情况下依然发出了sql将其查询了出来-----------
DEBUG [com.tabchanj.mybatis.domain.UserMapper.get] - ==> Preparing: select * from t_user where id = ?
DEBUG [com.tabchanj.mybatis.domain.UserMapper.get] - ==> Parameters: 1(Long)
DEBUG [com.tabchanj.mybatis.domain.DepartmentMapper.get] - ooo Using Connection [[email protected]]
DEBUG [com.tabchanj.mybatis.domain.DepartmentMapper.get] - ==> Preparing: select * from t_department where id = ?
DEBUG [com.tabchanj.mybatis.domain.DepartmentMapper.get] - ==> Parameters: 1(Long)
--------------------------------------------------------------------------------------------------------------------------
解决办法是,在mabtatis-config.xml中配置延迟加载属性,此时可以解决在查询user时不会查询department对象,
但是问题依然存在,,就是在查询User的任意一个属性时还是会发送额外的sql去查询department,
<settings> <setting name="lazyLoadingEnabled" value="true" /> </settings>
-----------------------------------------------------------------------------------------------------------------------
查询User的任意一个属性时还是会发送额外的sql去查询department,的解决方法
在mabtatis-config.xml中配置另一个延迟加载属性,
<setting name="aggressiveLazyLoading" value="false" />
-------------------------------------------------------------------------------------------------------------------------
---------------详细的mybatis-config.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> <settings> <setting name="lazyLoadingEnabled" value="true" /> <setting name="aggressiveLazyLoading" value="false" /> </settings> <typeAliases> <package name="com.tabchanj.mybatis.domain" /> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="org.gjt.mm.mysql.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> <property name="username" value="root" /> <property name="password" value="4230" /> </dataSource> </environment> </environments> <mappers> <mapper resource="com/tabchanj/mybatis/domain/UserMapper.xml" /> <mapper resource="com/tabchanj/mybatis/domain/DepartmentMapper.xml" /> </mappers> </configuration>
方式1的改进(嵌套结果):
不再在进行resultMap配置时使用sql语句进行二次查询,,此时直接先将department的所有属性全部查询出来,
和User的所有属性查在一张表中,当然此处需对department查询处的列名进行自定义别名,使列名更加有意义,,
是针对User和department中有同名属性造成查询出来的列名被标记为xxx1,xx2的清况.
-----------------------改进后的User的mapper映射配置文件------------------------<?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.tabchanj.mybatis.domain.UserMapper"> <resultMap type="com.tabchanj.mybatis.domain.User" id="UserMap"> <!-- User的基本属性 --> <id property="id" column="id"/> <result property="name" column="name"/> <!-- property:表示本类中关联的对象属性 并将关联对象的列名的别名与关联对象的属性做对应 --> <association property="dept" javaType="Department"> <id column="dept_id" property="id" /> <result column="dept_name" property="name" /> <result column="dept_sn" property="sn" /> </association> </resultMap> <select id="get" parameterType="Long" resultMap="UserMap"> <!-- 此时先将department的数据一并查询出来 --> select u.*,d.name dept_name,d.sn dept_sn from t_user u LEFT JOIN t_department d on u.dept_id=d.id where u.id = #{cc} </select> <select id="list" resultMap="UserMap"> select u.*,d.name dept_name,d.sn dept_sn from t_user u LEFT JOIN t_department d on u.dept_id=d.id </select> </mapper>
-------------------------测试------------------ @Test public void testName1() throws Exception { //通过sqlsession获得代理对象(Mapper) UserMapper mapper = MyBatisUtil.openSession().getMapper(UserMapper.class); //mapper调用接口中方法,相当于执行了mapper映射文件中的id为get的sql语句 User u = mapper.get(2L); System.out.println(u.getDept()); } 结果:只有一条sql,当然也只能有一条sql,因为一条sql就已经查出了本类和关联对象的所有信息
ybatis.domain.UserMapper.get] - ooo Using Connection [[email protected]] ybatis.domain.UserMapper.get] - Preparing: select u.*,d.name dept_name,d.sn dept_sn from t_user u LEFT JOIN t_department d on u.dept_id=d.id where u.id = ? ybatis.domain.UserMapper.get] - Parameters: 2(Long) Department [id=2, name=武装部, sn=FDSS]
方式2的该进(加前缀):
由于我们在自定义关联对象的列别名时都加了dept_的前缀,因此配置user的mapper时,可以在方式2中的association标签上添加columnPrefix="dept_"这一属性,
而内部就不再配置列名和属性名的对应了.但前提是,在Department的mapper映射配置文件中已经配置类简单的列名和属性相同的一一对应的resultMap标签.
并且,在user中的assosiation标签中还要引入该resultMap,详见下面的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.tabchanj.mybatis.domain.UserMapper"> <resultMap type="com.tabchanj.mybatis.domain.User" id="UserMap"> <!-- User的基本属性 --> <id property="id" column="id" /> <result property="name" column="name" /> <!-- property:表示本类中关联的对象属性 columnPrefix:表示关联对象的列名前都有 dept_ resultMap:指明返回的类型时department类型,之一resultMap路径department的mapper映射配置文件中的resultMap的路径 --> <association property="dept" javaType="Department" columnPrefix="dept_" resultMap="com.tabchanj.mybatis.domain.DepartmentMapper.DepartmentMap"> <!-- <id column="dept_id" property="id" /> --> <!-- <result column="dept_name" property="name" /> --> <!-- <result column="dept_sn" property="sn" /> --> </association> </resultMap> <select id="get" parameterType="Long" resultMap="UserMap"> <!-- 此时先将department的数据一并查询出来 --> select u.*,d.name dept_name,d.sn dept_sn from t_user u LEFT JOIN t_department d on u.dept_id=d.id where u.id = #{cc} </select> <select id="list" resultMap="UserMap"> select u.*,d.name dept_name,d.sn dept_sn from t_user u LEFT JOIN t_department d on u.dept_id=d.id </select> </mapper>
方式3:关联集合的查询
此时,时department中关联了User,此时为一对多的情况
此时,在department的mapper映射文件中的resultMap标签中采用<collection>子标签来关联User
-----------------department的mapper映射配置文件-----------------------<?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.tabchanj.mybatis.domain.DepartmentMapper"> <resultMap type="Department" id="DepartmentMap"> <id column="id" property="id" /> <result column="name" property="name" /> <result column="sn" property="sn" /> <!-- property:指明本类users属性 ofType:指明users集合中装的时User类型的数据 select:该查询语句还是使用的是user的mapper映射配置文件中的查询语句,从路径就可以看出 column:指明该查询语句中的参数时本类中的id列的值 --> <collection property="users" ofType="User" select="com.tabchanj.mybatis.domain.UserMapper.getByDeptId" column="id"> </collection> </resultMap> <select id="get" parameterType="Long" resultMap="DepartmentMap"> select * from t_department where id = #{id} </select> <select id="list" resultMap="DepartmentMap"> select * from t_department </select> </mapper>
-------User的mapper映射配置文件(只保留了
id="getByDeptId"的sql查询语句
)--------------------<?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.tabchanj.mybatis.domain.UserMapper"> <resultMap type="com.tabchanj.mybatis.domain.User" id="UserMap"> <!-- User的基本属性 --> <id property="id" column="id" /> <result property="name" column="name" /> </resultMap><!-- 该语句在department的mapper映射配置文件中被引用--> <select id="getByDeptId" parameterType="Long" resultMap="UserMap"> select * from t_user where dept_id=#{id} </select> </mapper>
// --------测试类----------- @Test public void testName2() throws Exception { // 通过sqlsession获得代理对象(Mapper) DepartmentMapper demapper = MyBatisUtil.openSession().getMapper(DepartmentMapper.class); // mapper调用接口中方法,相当于执行了mapper映射文件中的id为get的sql语句 Department d = demapper.get(1L); System.out.println(d); }结果:出现了2条sql语句,,并且是在已经配置了延迟加载的情况下出现的2条语句,说明该种方式不支持延迟加载
[com.tabchanj.mybatis.domain.DepartmentMapper.get] - ==> Preparing: select * from t_department where id = ? [com.tabchanj.mybatis.domain.DepartmentMapper.get] - ==> Parameters: 1(Long) [com.tabchanj.mybatis.domain.UserMapper.getByDeptId] - ooo Using Connection [[email protected]] DEBUG [com.tabchanj.mybatis.domain.UserMapper.getByDeptId] - ==> Preparing: select * from t_user where dept_id=? DEBUG [com.tabchanj.mybatis.domain.UserMapper.getByDeptId] - ==> Parameters: 1(Long) Department [id=1, name=财务部, sn=DFSD]