我尝试用 MyBatis 3.2.8 映射集合的反向关系。看起来 MyBatis 会复制对象,即使它们具有相同的 id。

public class ObjA { 
    private String id; 
    private ArrayList<ObjB> objBs; 
 
    // Getters, setters ... 
 
    // Equals based on the id field 
} 
 
public class ObjB { 
    private String id; 
    private ObjA objA; 
 
    // Getters, setters ... 
 
    // Equals based on the id field 
} 

映射xml文件

<resultMap id="xx" type="ObjA"> 
    <id column="idA" property="id" /> 
    <collection property="objBs" javaType="ArrayList" ofType="ObjB"> 
        <id column="idB" property="id"/> 
        <association property="objA" type="ObjA"> 
            <id column="idA" property="id" /> 
        </association> 
    </collection> 
</resultMap> 

JUnit 测试

ArrayList<ObjA> result = service.getAllObjA(); 
 
for(ObjA objA : result) { 
    for(ObjB objB : objA.getObjBs()) { 
        assertEquals(objB.getObjA(), objA); // Pass 
        assertTrue(objB.getObjA() == objA); // Does not pass 
    } 
} 

我希望 objB.getObjA()objA 是 ObjA 的同一个实例(同一个引用)。

我如何配置我的结果映射才能使其正常工作。

请您参考如下方法:

您描述的POJO的ObjAObjB循环依赖

考虑以下示例:让我们有一个Artist 类和一个Recording 类。它们不需要实现 Comparable 接口(interface),但我们这样做是因为我们要对这些对象进行排序。或者,可以编写 SQL 查询以指定返回行的所需排序顺序。

这是艺术家类。请注意,艺术家持有其录音的集合。

import java.util.List; 
 
public class Artist implements Comparable { 
 
  private int id; 
  private List<Recording> recordings; 
  private String name; 
 
  public Artist() {} 
  public Artist(String name) { this.name = name; } 
 
  public int compareTo(Object obj) { 
    Artist r = (Artist) obj; 
    return name.compareTo(r.name); 
  } 
 
  public int getId() { return id; } 
  public void setId(int id) { this.id = id; } 
 
  public String getName() { return name; } 
  public void setName(String name) { 
    this.name = name; 
  } 
 
  public List<Recording> getRecordings() { return recordings; } 
  public void setRecordings(List<Recording> recordings) { 
    this.recordings = recordings; 
  } 
} 

这是 Recording 类。请注意,录音包含对其艺术家的引用。

public class Recording implements Comparable { 
 
  private int id; 
  private int year; 
  private Artist artist; 
  private String name; 
 
  public Recording() {} 
  public Recording(Artist artist, String name, int year) { 
    this.artist = artist; 
    this.name = name; 
    this.year = year; 
  } 
 
  public int compareTo(Object obj) { 
    Recording r = (Recording) obj; 
    return name.compareTo(r.name); 
  } 
 
  public Artist getArtist() { return artist; } 
  public void setArtist(Artist artist) { this.artist = artist; } 
 
  public int getId() { return id; } 
  public void setId(int id) { this.id = id; } 
 
  public String getName() { return name; } 
  public void setName(String name) { this.name = name; } 
 
  public int getYear() { return year; } 
  public void setYear(int year) { this.year = year; } 
} 

配置:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE sqlMapConfig 
  PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" 
  "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> 
 
<sqlMapConfig> 
 
  <settings useStatementNamespaces="true"/> 
 
  <transactionManager type="JDBC"> 
    <dataSource type="SIMPLE"> 
      <property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/> 
      <property name="JDBC.ConnectionURL" 
        value="jdbc:mysql://localhost:3306/music"/> 
      <property name="JDBC.Username" value="root"/> 
      <property name="JDBC.Password" value=""/> 
    </dataSource> 
  </transactionManager> 
 
  <sqlMap resource="Artist.xml"/> 
  <sqlMap resource="Recording.xml"/> 
 
</sqlMapConfig> 

映射语句在从 SqlMapConfig.xml 文件引用的 XML 文件中定义。

这是指定与我们的艺术家表相关的语句的文件。

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE sqlMap 
  PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" 
  "http://ibatis.apache.org/dtd/sql-map-2.dtd"> 
 
<sqlMap namespace="Artist"> 
 
  <delete id="deleteAll"> 
    delete from artists 
  </delete> 
 
  <insert id="insert" parameterClass="com.ociweb.music.Artist"> 
    insert into artists (name) values (#name#) 
    <selectKey resultClass="int" keyProperty="id"> 
      select last_insert_id() as id 
    </selectKey> 
  </insert> 
 
  <resultMap id="result" class="com.ociweb.music.Artist"> 
    <result property="id" column="id"/> 
    <result property="name" column="name"/> 
    <!-- This results in N+1 selects. To avoid this, see page 40 
         in the iBATIS Developer Guide. --> 
    <result property="recordings" column="id" 
      select="Recording.getByArtist"/> 
  </resultMap> 
 
  <select id="getById" 
    parameterClass="java.lang.Integer" resultMap="result"> 
    select * from artists where id=#id# 
  </select> 
 
  <select id="getAll" resultClass="com.ociweb.music.Artist"> 
    select * from artists 
  </select> 
 
</sqlMap> 

这是指定与我们的记录表相关的语句的文件。

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE sqlMap 
  PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" 
  "http://ibatis.apache.org/dtd/sql-map-2.dtd"> 
 
<sqlMap namespace="Recording"> 
 
  <delete id="deleteAll"> 
    delete from recordings 
  </delete> 
 
  <insert id="insert" parameterClass="com.ociweb.music.Recording"> 
    insert into recordings (name, year, artist_id) 
    values (#name#, #year#, #artist.id#) 
    <selectKey resultClass="int" keyProperty="id"> 
      select last_insert_id() as id 
    </selectKey> 
  </insert> 
 
  <resultMap id="resultWithoutArtist" class="com.ociweb.music.Recording"> 
    <result property="id" column="id"/> 
    <result property="name" column="name"/> 
    <result property="year" column="year"/> 
  </resultMap> 
 
  <resultMap id="result" 
    class="com.ociweb.music.Recording" extends="resultWithoutArtist"> 
    <result property="artist" column="artist_id" select="Artist.getById"/> 
  </resultMap> 
 
  <select id="getAll" resultClass="com.ociweb.music.Recording"> 
    select * from recordings 
  </select> 
 
  <!-- resultWithoutArtist is used here to avoid a circular 
       dependency when Artist.result (in Artist.xml) is used. --> 
  <select id="getByArtist" 
    parameterClass="java.lang.Integer" resultMap="resultWithoutArtist"> 
    select * from recordings where artist_id=#artistId# 
  </select> 
 
  <select id="getByYear" 
    parameterClass="java.lang.Integer" resultMap="result"> 
    select * from recordings where year=#year# 
  </select> 
 
</sqlMap> 

Find the Complete Example


评论关闭
IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!