Mybatis - 从SELECT返回包含Hashmap的对象

时间:2014-09-10 11:25:15

标签: java mysql hashmap mybatis

我正在使用Mybatis-3,我有以下情况:

我有Class - User,如下所示:

public class User extends GeneralDto {

    private String userId;
    private String email;
    private String firstName;
    private String lastName;
    private long creationTimestamp;
    private long updateTimestamp;
    private List<String> tags;
    private HashMap<String, String> attributes;
    private HashMap<String, String> accounts;

    get and set to all + equals + hashcode.
}

这两个哈希映射包含未知的键和String类型的值(它们给我带来了很多麻烦)。

我已经使用insert方法将此类映射到表中。并将其映射到以下表格方案:

User (userIdentity, userId, email, firstName, lastName, creationTimestamp, updateTimestamp)

UserAttribute (userIdentity, attributeName, attributeValue, creationTimestamp, updateTimestamp)

UserTag (userIdentity, tagName, creationTimestamp, updateTimestamp)

UserAccount (userIdentity, accountIdentity, role, creationTimestamp, updateTimestamp)

我需要创建一个GET方法。该方法接收UserKey对象,该对象包含userId,userId是用户的密钥。并返回用户类的实例。

这是SELECT语句,它连接所有表并从每个表中获取相关数据:

<select id="getUser" parameterType="com.intel.aa.iot.mybatis.UserResultHandler" resultMap="userResultMap" resultOrdered="true">
    SELECT
        U.userId as userId,
        U.email as email,
        U.firstName as firstName,
        U.lastName as lastName,
        U.creationTimestamp as creationTimestamp,
        U.updateTimestamp as updateTimestamp,
        UT.tagName as tagName,
        UAT.attributeName as attributeName,
        UAT.attributeValue as attributeValue,
        A.accountId as accountId,
        UAC.role as role
    FROM User U
        LEFT OUTER JOIN UserTag UT ON U.userIdentity = UT.userIdentity
        LEFT OUTER JOIN UserAttribute UAT ON U.userIdentity = UAT.userIdentity
        LEFT OUTER JOIN UserAccount UAC ON U.userIdentity = UAC.userIdentity
        LEFT OUTER JOIN ACCOUNTS A ON UAC.accountIdentity = A.accountIdentity
    WHERE U.userId = #{userKey.userId}

由于连接,此查询可能返回多行,但所有行都是给定的userId。

我的问题是如何将其映射到一个结果,这是一个用户类的实例。 我尝试使用结果映射但遇到了映射hashmap的问题。 然后我尝试使用ResultHandler - 返回名为UserProperties的类,它将每个hashmap包含为两个列表(请参阅下面的代码),但不幸的是它也没有工作 - 最终只保存了每个列表的一个值。

UserProperties类:

public static class UserProperties {
    private User user;
    private List<String> attributeNames;
    private List<String> attributeValues;
    private List<String> accountIds;
    private List<String> accountRoles;

    get and set to all
}

的ResultMap:

<resultMap id="userResultMap" type="com.intel.aa.iot.mybatis.UserMapper$UserProperties">
    <association property="user" javaType="com.intel.aa.iot.dto.User">
        <id property="userId" column="userId"/>
        <result property="email" column="email"/>
        <result property="firstName" column="firstName"/>
        <result property="lastName" column="lastName"/>
        <result property="creationTimestamp" column="creationTimestamp"/>
        <result property="updateTimestamp" column="updateTimestamp"/>
        <collection property="tags" javaType="java.util.ArrayList" column="tagName" ofType="java.lang.String"/>
    </association>
    <collection property="attributeNames"  javaType="java.util.ArrayList" column="attributeName" ofType="java.lang.String"/>
    <collection property="attributeValues" javaType="java.util.ArrayList" column="attributeValue" ofType="java.lang.String"/>
    <collection property="accountIds" javaType="java.util.ArrayList" column="accountId" ofType="java.lang.String"/>
    <collection property="accountRoles" javaType="java.util.ArrayList" column="role" ofType="java.lang.String"/>
</resultMap>

我处理这些Hasmaps的方法是什么?

谢谢!

1 个答案:

答案 0 :(得分:3)

在过去的几年里,我自己也遇到过同样的问题,但我还没有找到理想的解决方案。最终问题是mybatis不允许你指定hashmap的键 - 它使用结果属性名作为键。

我采取的两种解决方法远非完美,但我会在这里概述它们,以防它们对你有用:

  1. 使用结果处理程序。我看到你说你已经尝试了这个,但只获得了第一个价值 - 你有可能分享你的代码吗?在查询中返回的每行调用一次结果处理程序,因此您不希望每次都创建一个新对象。只有当您还没有与此行中的ID匹配的对象时,才想创建对象,然后根据以下行迭代地构建它。

  2. 将名称和值构建为井号图列表,然后使用select拦截器(mybatis插件)调用对象内部的方法来构建真实的哈希图。为此,在结果映射中,您需要在类型为hashmap的关联下指定名称和值结果。然后Mybatis会把它变成一个看起来像这样的列表:

    [List [Hashmap {“attributeName”= name1,“attributeValue”= value1}],[Hashmap {“attributeName”= name2,“attributeValue”= value2}]]

  3. 然后,您可以在拦截器中调用迭代此hashmap的方法来构建所需的hashmap。

    两种解决方案都不是很好。第一种解决方案失去了结果映射的优雅,第二种解决方案污染了您的域对象。但如果您对进一步的细节感兴趣,请告诉我,我将添加一些代码示例。