Mybatis 示例之 Association (2)

  1. 云栖社区>
  2. 博客>
  3. 正文

Mybatis 示例之 Association (2)

yemon 2016-03-17 11:12:00 浏览1207
展开阅读全文

上一篇讲到了association的关联结果查询,这里讲association的关联的嵌套查询,这种方式用起来很容易,和关联结果查询相比缺点就是会执行关联SQL,增加一定的查询。


关联的嵌套查询

属性 描述
column 来自数据库的类名,或重命名的列标签。这和通常传递给resultSet.getString(columnName)方法的字符串是相同的。column注 意 : 要 处 理 复 合 主 键 , 你 可 以 指 定 多 个 列 名 通 过 column= ”{prop1=col1,prop2=col2} ” 这种语法来传递给嵌套查询语 句。这会引起prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。
select 另外一个映射语句的 ID,可以加载这个属性映射需要的复杂类型。获取的在列属性中指定的列的值将被传递给目标 select 语句作为参数。表格后面有一个详细的示例。select注 意 : 要 处 理 复 合 主 键 , 你 可 以 指 定 多 个 列 名 通 过 column= ”{prop1=col1,prop2=col2} ” 这种语法来传递给嵌套查询语 句。这会引起prop1 和 prop2 以参数对象形式来设置给目标嵌套查询语句。


下面是测试用的Mapper.xml文件:

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE mapper  
  3.     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  4.     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  5.   
  6. <mapper namespace="org.apache.ibatis.submitted.associationtype.Mapper">  
  7.   
  8.  <resultMap id="sampleHashResult" type="hashmap">  
  9.     <result property="f1" column="f1" />  
  10.     <result property="f2" column="f2" />  
  11.     <association property="a1" javaType="java.lang.String"  
  12.         column="{param1=f1}" select="associationTest" />  
  13.     <association property="a2" javaType="java.lang.String"  
  14.         column="{param1=f1}" select="associationTest" />  
  15.     </resultMap>  
  16.   
  17.     <select id="getUser" resultMap="sampleHashResult">  
  18.         SELECT id as f1, name as f2 from users   
  19.     </select>  
  20.       
  21.     <select id="associationTest" resultType="java.lang.String">  
  22.         select id from users   
  23.     </select>  
  24.       
  25. </mapper>  

下面是测试用的代码:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class AssociationTypeTest {  
  2.   
  3.   private static SqlSessionFactory sqlSessionFactory;  
  4.   
  5.   @BeforeClass  
  6.   public static void setUp() throws Exception {  
  7.     // create a SqlSessionFactory  
  8.     Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/associationtype/mybatis-config.xml");  
  9.     sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);  
  10.     reader.close();  
  11.   
  12.     // populate in-memory database  
  13.     SqlSession session = sqlSessionFactory.openSession();  
  14.     Connection conn = session.getConnection();  
  15.     reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/associationtype/CreateDB.sql");  
  16.     ScriptRunner runner = new ScriptRunner(conn);  
  17.     runner.setLogWriter(null);  
  18.     runner.runScript(reader);  
  19.     reader.close();  
  20.     session.close();  
  21.   }  
  22.   
  23.   @Test  
  24.   public void shouldGetAUser() {  
  25.     SqlSession sqlSession = sqlSessionFactory.openSession();  
  26.     try {  
  27.       List<Map> results = sqlSession.selectList("getUser");  
  28.       for (Map r : results) {  
  29.           Assert.assertEquals(String.class, r.get("a1").getClass());  
  30.           Assert.assertEquals(String.class, r.get("a2").getClass());  
  31.       }  
  32.     } finally {  
  33.       sqlSession.close();  
  34.     }  
  35.   }  
  36.   
  37. }  

下面是mybatis的配置文件:

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <!DOCTYPE configuration  
  2.     PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
  3.     "http://mybatis.org/dtd/mybatis-3-config.dtd">  
  4.   
  5. <configuration>  
  6.   
  7.     <environments default="development">  
  8.         <environment id="development">  
  9.             <transactionManager type="JDBC">  
  10.                 <property name="" value="" />  
  11.             </transactionManager>  
  12.             <dataSource type="UNPOOLED">  
  13.                 <property name="driver" value="org.hsqldb.jdbcDriver" />  
  14.                 <property name="url" value="jdbc:hsqldb:mem:associationtype" />  
  15.                 <property name="username" value="sa" />  
  16.             </dataSource>  
  17.         </environment>  
  18.     </environments>  
  19.   
  20.     <mappers>  
  21.         <mapper resource="org/apache/ibatis/submitted/associationtype/Mapper.xml" />  
  22.     </mappers>  
  23.   
  24. </configuration>  
最后是测试用的表结构和数据:

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. drop table users if exists;  
  2.   
  3. create table users (  
  4.   id int,  
  5.   name varchar(20)  
  6. );  
  7.   
  8. insert into users (id, namevalues(1, 'User1');  

程序运行情况:


可以看到这里的结果results完全符合。


下面来分析执行过程:

首先系统调用的getUser方法,执行下面的SQL:

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. SELECT id as f1, name as f2 from users   

执行完上面的SQL之后(在上面Mapper.xml的配置中column="{param1=f1}"并没有起到作用,如果往users表中插入多条数据,这里肯定会报错。先不说这种情况。),再通过嵌套对象的SQL来执行,最终返回上面的结果。


下面在上面测试的基础上进行修改(下面代码只显示改动过的地方):

[sql] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. insert into users (id, namevalues(1, 'User1');  
  2. insert into users (id, namevalues(2, 'User2');  
  3. insert into users (id, namevalues(3, 'User3');  

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <resultMap id="sampleHashResult" type="hashmap">  
  2.     <result property="f1" column="f1" />  
  3.     <result property="f2" column="f2" />  
  4.     <association property="a1" javaType="java.lang.String"  
  5.         column="{id=f1}" select="associationTest" />  
  6.     <association property="a2" javaType="java.lang.String"  
  7.         column="{id=f2}" select="associationTest" />  
  8. </resultMap>  
  9.   
  10. <select id="getUser" resultMap="sampleHashResult">  
  11.     SELECT 1 as f1, 2 as f2 from (VALUES(0))  
  12. </select>  
  13.   
  14. <select id="associationTest" resultType="java.lang.String">  
  15.     select name from users where  id = #{id}  
  16. </select>  

在users表中增加了两条数据。

association中一个改为id=f1,一个改为id=f2


将associationTest中的sql改为select name from users where id = #[id},将getUser改为了select 1 as f1,2 as f2 from (values(0)

注:这里的from (values(0))类似于oracle中的from dual


执行结果如下:



这里需要注意的地方:

 column="{id=f1}",在column中id是要执行SQL中接收到的参数,f1是原SQL中的查询结果。这里是将原SQL查询结果放到将要执行SQL中当条件,当有多个条件时,可以用逗号隔开。


上面讲的用法还是太简单,因为执行的SQL返回的是String,现在我们创建一个Users类,然后将返回结果改为POJO类。

Users类:


XML:

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <resultMap id="sampleHashResult" type="hashmap">  
  2.     <result property="f1" column="f1" />  
  3.     <result property="f2" column="f2" />  
  4.     <association property="a1" javaType="org.apache.ibatis.submitted.associationtype.Users"  
  5.         column="{id=f1}" select="associationTest" />  
  6.     <association property="a2" javaType="org.apache.ibatis.submitted.associationtype.Users"  
  7.         column="{id=f2}" select="associationTest" />  
  8. </resultMap>  
  9.       
  10. <select id="associationTest" resultType="org.apache.ibatis.submitted.associationtype.Users">  
  11.     select * from users where  id = #{id}  
  12. </select>  
xml中只是将原来的java.lang.String改为了Users类。

执行测试方法,返回结果如下:




是不是发现改成POJO对象也很容易,而且这里相对于关联结果查询不需要配置resultMap,方便很多。到这里,关于association的内容就讲完了,接下来会介绍其他Mybatis的有关内容。


如果有association方面问题可以参考(或在此留言):

http://mybatis.github.io/mybatis-3/zh/sqlmap-xml.html

本节源码请看官方git:

https://github.com/mybatis/mybatis-3/tree/master/src/test/java/org/apache/ibatis/submitted/associationtype

网友评论

登录后评论
0/500
评论
yemon
+ 关注