Mybatis 示例之 Association (2)
上一篇講到了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>
xml中只是將原來的java.lang.String改為了Users類。
執行測試方法,返回結果如下:
是不是發現改成POJO物件也很容易,而且這裡相對於關聯結果查詢不需要配置resultMap,方便很多。到這裡,關於association的內容就講完了,接下來會介紹其他Mybatis的有關內容。
如果有association方面問題可以參考(或在此留言):
http://mybatis.github.io/mybatis-3/zh/sqlmap-xml.html
本節原始碼請看官方git: