0

Let's assume this simple schema:

create table User (
  identity BIGINT UNSIGNED, PRIMARY KEY (identity), 
  name VARCHAR(32) NOT NULL);
create table Role (
  identity BIGINT UNSIGNED, PRIMARY KEY (identity), 
  name VARCHAR(32) NOT NULL);
create table UserRole (
  user_identity BIGINT UNSIGNED REFERENCES User (identity), 
  role_identity BIGINT UNSIGNED REFERENCES Role (identity), 
  PRIMARY KEY(user_identity, role_identity)); 

And this mapping in MyBatis:

<select id="SelectUserById" parameterType="long" resultMap="UserResultMap">
  select
    u.identity as u_identity,
    u.name as u_name,
    r.identity as r_identity,
    r.name as r_name
  from
    User u
    inner join UserRole ur on ur.user_identity = u.identity
    inner join Role r on ur.role_identity = r.identity
  where
    u.identity = #{id}
</select>

<resultMap id="UserResultMap" type="User">
    <id property="identity" column="u_identity" />
    <result property="name" column="u_name" />
    <collection property="roles" column="u_identity" ofType="Role" javaType="ArrayList">
        <id property="identity" column="r_identity" />
        <result property="name" column="r_name" />
    </collection>
</resultMap>

Here's the implementation of my User bean:

public class User {

    private Long identity;
    private String name;
    private List<Role> roles = new ArrayList<Role>();

    public Long getIdentity() {
        return identity;
    }

    public void setIdentity(Long identity) {
        this.identity = identity;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Role> getRoles() {
        return new ArrayList<Role>(roles);
    }

    public void setRoles(List<Role> roles) {
        this.roles = new ArrayList<Role>(roles);
    }
} 

So everything is pretty straightforward except for the fact that I take defensive copies from the role list in my user bean implementation. The problem is that MyBatis does not seem to support this at all and the resulting role list will be empty. If I don't take these copies it works smoothly but would be poor design. Is there a way around this?

Muton
  • 761
  • 2
  • 7
  • 16
  • actually, the whole "defensive" copies thing _itself_ is generally a poor and fairly inefficient design. – jtahlborn Mar 30 '12 at 17:00
  • Well, that's debatable and depends on the context. A bit more efficient solution would perhaps be to return `Collections.unmodifiableList(roles)` but that will cause an exception in MyBatis. – Muton Mar 30 '12 at 17:48
  • Anyway, my intention is not to debate about this decision itself but instead to know if it's possible to use MyBatis with it. – Muton Mar 30 '12 at 17:48
  • well, your defensive copy is only a partial copy nyway, because you are still sharing mutable Role instances (and therefore things could still be modified out from under you). ultimately, my point is that using mybatis as it is designed makes more sense than partial defensive copying. – jtahlborn Mar 30 '12 at 17:51
  • I appreciate your feedback but to me it's not a option change this fact and therefore would like to find a way around it if possible. – Muton Mar 30 '12 at 18:05
  • @Muton did you ever figure out a way to do this? – Nick Jun 30 '16 at 22:49

0 Answers0