上一篇讲到了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文件:
- <?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="org.apache.ibatis.submitted.associationtype.Mapper">
- <resultMap id="sampleHashResult" type="hashmap">
- <result property="f1" column="f1" />
- <result property="f2" column="f2" />
- <association property="a1" javaType="java.lang.String"
- column="{param1=f1}" select="associationTest" />
- <association property="a2" javaType="java.lang.String"
- column="{param1=f1}" select="associationTest" />
- </resultMap>
- <select id="getUser" resultMap="sampleHashResult">
- SELECT id as f1, name as f2 from users
- </select>
- <select id="associationTest" resultType="java.lang.String">
- select id from users
- </select>
- </mapper>
下面是测试用的代码:
- public class AssociationTypeTest {
- private static SqlSessionFactory sqlSessionFactory;
- @BeforeClass
- public static void setUp() throws Exception {
- // create a SqlSessionFactory
- Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/associationtype/mybatis-config.xml");
- sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
- reader.close();
- // populate in-memory database
- SqlSession session = sqlSessionFactory.openSession();
- Connection conn = session.getConnection();
- reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/associationtype/CreateDB.sql");
- ScriptRunner runner = new ScriptRunner(conn);
- runner.setLogWriter(null);
- runner.runScript(reader);
- reader.close();
- session.close();
- }
- @Test
- public void shouldGetAUser() {
- SqlSession sqlSession = sqlSessionFactory.openSession();
- try {
- List<Map> results = sqlSession.selectList("getUser");
- for (Map r : results) {
- Assert.assertEquals(String.class, r.get("a1").getClass());
- Assert.assertEquals(String.class, r.get("a2").getClass());
- }
- } finally {
- sqlSession.close();
- }
- }
- }
下面是mybatis的配置文件:
- <!DOCTYPE configuration
- PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
- <environments default="development">
- <environment id="development">
- <transactionManager type="JDBC">
- <property name="" value="" />
- </transactionManager>
- <dataSource type="UNPOOLED">
- <property name="driver" value="org.hsqldb.jdbcDriver" />
- <property name="url" value="jdbc:hsqldb:mem:associationtype" />
- <property name="username" value="sa" />
- </dataSource>
- </environment>
- </environments>
- <mappers>
- <mapper resource="org/apache/ibatis/submitted/associationtype/Mapper.xml" />
- </mappers>
- </configuration>
- drop table users if exists;
- create table users (
- id int,
- name varchar(20)
- );
- insert into users (id, name) values(1, 'User1');
程序运行情况:
可以看到这里的结果results完全符合。
下面来分析执行过程:
首先系统调用的getUser方法,执行下面的SQL:
- SELECT id as f1, name as f2 from users
执行完上面的SQL之后(在上面Mapper.xml的配置中column="{param1=f1}"并没有起到作用,如果往users表中插入多条数据,这里肯定会报错。先不说这种情况。),再通过嵌套对象的SQL来执行,最终返回上面的结果。
下面在上面测试的基础上进行修改(下面代码只显示改动过的地方):
- insert into users (id, name) values(1, 'User1');
- insert into users (id, name) values(2, 'User2');
- insert into users (id, name) values(3, 'User3');
- <resultMap id="sampleHashResult" type="hashmap">
- <result property="f1" column="f1" />
- <result property="f2" column="f2" />
- <association property="a1" javaType="java.lang.String"
- column="{id=f1}" select="associationTest" />
- <association property="a2" javaType="java.lang.String"
- column="{id=f2}" select="associationTest" />
- </resultMap>
- <select id="getUser" resultMap="sampleHashResult">
- SELECT 1 as f1, 2 as f2 from (VALUES(0))
- </select>
- <select id="associationTest" resultType="java.lang.String">
- select name from users where id = #{id}
- </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:
- <resultMap id="sampleHashResult" type="hashmap">
- <result property="f1" column="f1" />
- <result property="f2" column="f2" />
- <association property="a1" javaType="org.apache.ibatis.submitted.associationtype.Users"
- column="{id=f1}" select="associationTest" />
- <association property="a2" javaType="org.apache.ibatis.submitted.associationtype.Users"
- column="{id=f2}" select="associationTest" />
- </resultMap>
- <select id="associationTest" resultType="org.apache.ibatis.submitted.associationtype.Users">
- select * from users where id = #{id}
- </select>
执行测试方法,返回结果如下:
是不是发现改成POJO对象也很容易,而且这里相对于关联结果查询不需要配置resultMap,方便很多。到这里,关于association的内容就讲完了,接下来会介绍其他Mybatis的有关内容。
如果有association方面问题可以参考(或在此留言):
http://mybatis.github.io/mybatis-3/zh/sqlmap-xml.html
本节源码请看官方git: