2016-11-30 18 views
1

のリストのプロパティのフェッチリストは、私がDTOクラスを以下していると仮定します2つのクエリーで検索されます(項目は1番目、詳細は2番目)。以下の例では、N + 1個のクエリ(N個のアイテム)が存在します。MyBatisのオブジェクト

(サンプル・スキーマ、試験データおよび使用のための)完全例
Sandbox.java:

import org.apache.ibatis.io.Resources; 
import org.apache.ibatis.session.*; 

import java.sql.*; 
import java.sql.Statement; 
import java.util.List; 

public class Sandbox { 
    public static void main(String... args) throws Throwable { 
     try (Connection connection = DriverManager.getConnection("jdbc:sqlite:sample.db")) { 
      try (Statement statement = connection.createStatement()) { 
       statement.executeUpdate("drop table if exists Item"); 
       statement.executeUpdate("create table Item (id integer)"); 


       statement.executeUpdate("insert into Item values(1)"); 
       statement.executeUpdate("insert into Item values(2)"); 

       statement.executeUpdate("drop table if exists Detail"); 
       statement.executeUpdate("create table Detail (id integer, name string, value string)"); 

       statement.executeUpdate("insert into Detail values(1, 'name', 'foo')"); 
       statement.executeUpdate("insert into Detail values(1, 'purpose', 'test')"); 
       statement.executeUpdate("insert into Detail values(2, 'name', 'bar')"); 
      } 
     } 

     SqlSessionFactory sqlSessionFactory = 
       new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); 

     try (SqlSession session = sqlSessionFactory.openSession()) { 
      MyMapper mapper = session.getMapper(MyMapper.class); 
      List<Item> items = mapper.selectItems(); 

      System.out.println("items = " + items); 
     } 
    } 
} 

MyMapper.java:

import java.util.List; 

public interface MyMapper { 
    List<Item> selectItems(); 
} 

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="MyMapper"> 
    <resultMap id="ItemMap" type="Item"> 
     <id column="id" property="id"/> 
     <collection column="id" property="details" select="selectDetails"/> 
    </resultMap> 

    <select id="selectItems" resultMap="ItemMap"> 
     select * from Item 
    </select> 

    <select id="selectDetails" parameterType="int" resultType="Detail"> 
     select * from Detail WHERE id=#{id} 
    </select> 
</mapper> 

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> 
    <environments default="development"> 
     <environment id="development"> 
      <transactionManager type="JDBC"/> 
      <dataSource type="POOLED"> 
       <property name="driver" value="net.sf.log4jdbc.DriverSpy"/> 
       <property name="url" value="jdbc:log4jdbc:sqlite:sample.db"/> 
      </dataSource> 
     </environment> 
    </environments> 
    <mappers> 
     <mapper resource="Mapper.xml"/> 
    </mappers> 
</configuration> 

のpom.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>ru.urururu</groupId> 
    <artifactId>mybatis-batching</artifactId> 
    <version>1.0-SNAPSHOT</version> 

    <dependencies> 
     <dependency> 
      <groupId>org.mybatis</groupId> 
      <artifactId>mybatis</artifactId> 
      <version>3.4.0</version> 
     </dependency> 

     <dependency> 
      <groupId>org.xerial</groupId> 
      <artifactId>sqlite-jdbc</artifactId> 
      <version>3.15.1</version> 
     </dependency> 

     <dependency> 
      <groupId>com.googlecode.log4jdbc</groupId> 
      <artifactId>log4jdbc</artifactId> 
      <version>1.2</version> 
     </dependency> 

     <dependency> 
      <groupId>org.slf4j</groupId> 
      <artifactId>slf4j-simple</artifactId> 
      <version>1.7.21</version> 
     </dependency> 
    </dependencies> 
    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-compiler-plugin</artifactId> 
       <version>3.6.0</version> 
       <configuration> 
        <source>1.8</source> 
        <target>1.8</target> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 
</project> 

答えて

1

あなたはマッパーそれが説明されているリファレンスドキュメントのXMLセクションMultiple ResultSets for Associationを見て取る場合:バージョン3.2.3から始まっ

MyBatisは、N + 1問題を 解決するためのさらに別の方法を提供します。

データベースによっては、複数のストアドプロシージャが結果セットを複数返したり、複数のステートメントを同時に実行したり、それぞれ1つにつき 結果セットを返すことができます。これは、データベースを一度だけヒットするために使用することができます。 と結合を使用せずに関連するデータを返します。

例があります。その後、選択は次のようにストアドプロシージャを呼び出します

select * from Item 
select * from Detail WHERE id=#{id} 

<select id="selectItems" resultSets="item,details" resultMap="ItemMap"> 
    {call getItemAndDetails(#{id,jdbcType=INTEGER,mode=IN})} 
</select> 

最後にresultmapに:

は「詳細ことを指定だから、クエリとストアドプロシージャを必要とします"詳細"という名前の結果セットに含まれているデータからコレクションが作成されます

結果マップで10

あなたのコレクションタグは、次のようなものになるだろう:

<collection property="details" ofType="Detail" resultSet="details" column="id" foreignColumn="foreign_id"> 
+0

私が必要ときたものだが、私はあなたがresultTypeと=「項目、ディテール」と間違えましたと信じて、のResultSetの= "項目でなければなりません、詳細 "を参照してください。 – okutane

+0

はい、あなたは正しい;) – Pau

+0

正確に2つの選択肢でそれを行う方法を知っていますか(ドライバが複数の結果セットをサポートしない場合)? – okutane