我正在调查MyBatis 3.0.5的映射工具。运行嵌入式模式时数据库为H2(1.3.160)。在用户手册的帮助下,我得到了直截了当的部分。但是我很难映射使用Set
作为后备存储的HashMap
。
以下是将自定义设置为字段的自定义集合的Java代码(为简洁起见而简化)
public class CustomCollection
{
@JsonProperty
private CustomSet<CustomItem> customItems;
public CustomCollection()
{
customItems = new CustomSet<CustomItem>();
}
// other stuff
}
这是CustomSet
代码(再次,简化)
public class CustomSet<E extends CustomItemInterface> extends AbstractSet<E>
{
private ConcurrentHashMap<String, E> items;
public CustomSet()
{
items = new ConcurrentHashMap<String, E>();
}
// other stuff
}
这是映射界面:
public interface CustomCollectionMapper
{
CustomCollection select(@Param("somename") String s1, @Param("someothername") String s2);
}
这是调用Mybatis框架的代码:
SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) servletContext.getAttribute("SqlSessionFactory");
SqlSession session = sqlSessionFactory.openSession();
CustomCollection coll = null;
try
{
CustomCollectionMapper mapper = session.getMapper(CustomCollectionMapper.class);
coll = mapper.select(param1, param2);
}
finally
{
session.close();
}
到目前为止,我可以提出映射XML:
<select id="select" resultMap="CustomCollectionMapping">
-- What goes here???
</select>
<resultMap type="com.example.CustomCollection" id="CustomCollectionMapping">
<association property="customItems" javaType="com.example.customSet">
<collection property="items" javaType="HashMap" ofType="com.example.CustomItem" select="selectCustomItems">
</collection>
</association>
</resultMap>
<select id="selectCustomItems" parameterType="map" resultType="com.example.CustomItem">
-- SQL query to return multiple CustomItem rows
</select>
通过各种迭代,我得到“太多结果”错误,一些其他错误或什么都没有(从mapper调用返回null)但从来没有我需要的结果。 SQL代码本身工作正常,如果我要求一个带有简单select语句的List,我会得到行和ArrayList。我遇到的问题是正确填充嵌套集合对象。
我已多次阅读本手册,搜索了示例但我无法为此目的提供正确的映射XML。如果有人能帮助我或指出一个可以提供帮助的来源,我将不胜感激。
提前感谢所有帮助。
答案 0 :(得分:1)
这是我的工作范例:
<resultMap id="categoryPreferenceValueMap" type="SyncCategoryPreferenceValueModel">
<id property="preferenceTypeId" column="preference_type_id" />
<result property="title" column="title"/>
<result property="index" column="type_index"/>
<result property="updatedAt" column="category_updated_at" />
<collection property="preferences" column="p_preference_id" ofType="SyncPreferenceModel" >
<id property="preferenceId" column="p_preference_id" />
<result property="title" column="p_preference_title" />
<result property="index" column="preference_index" />
<result property="updatedAt" column="preference_updated_at" />
<collection property="preferenceValues" column="p_v_preference_value_id" ofType="SyncPreferenceValueModel" >
<id property="preferenceValueId" column="p_v_preference_value_id" />
<result property="preferenceValue" column="p_v_preference_value" />
<result property="updatedAt" column="preference_value_updated_at" />
</collection>
</collection>
</resultMap>
这是我的查询
<select id="getPrefersenceWithValues" resultMap="categoryPreferenceValueMap">
SELECT
PT.preference_type_id, PT.title, PT.type_index,PT.updated_at as category_updated_at,
P.preference_id as p_preference_id , P.title as p_preference_title ,P.index as preference_index,
P.updated_at as preference_updated_at,
PV.preference_value_id as p_v_preference_value_id ,PV.preference_value as p_v_preference_value
FROM preference_types PT
INNER JOIN preferences P ON PT.preference_type_id=P.preference_type_id
INNER JOIN preference_values PV ON P.preference_id=PV.preference_id
ORDER BY type_index
</select>
输出是:
[
{
"preferenceTypeId": "1",
"title": "abc BASICS",
"index": "1",
"updatedAt": 1,
"preferences": [
{
"preferenceId": "1",
"title": "xyz xyz",
"preferenceTypeId": null,
"gender": null,
"index": 1,
"updatedAt": 1,
"preferenceValues": [
{
"preferenceId": null,
"preferenceValueId": "2",
"preferenceValue": "30-60",
"gender": null,
"updatedAt": 0
},
{
"preferenceId": null,
"preferenceValueId": "1",
"preferenceValue": "0-30",
"gender": null,
"updatedAt": 0
}
]
}
]
}
]
答案 1 :(得分:0)
您可能想尝试自定义ResultHandler。我想,你的CustomSet应该可行。我将进一步调查,如果我找到了什么,我会更新。
答案 2 :(得分:0)
看起来ResultHandler
可以解决这个问题,但这让我编写了大量代码,留下了XML映射工厂的好处。此外,每个返回行调用一次处理程序的事实令我担心。
我在a message in the mybatis-user group中发现Mybatis实际上不会做我想要的事情(即使我摆脱了中间人CustomSet
,看起来Mybatis看起来不会填充hashmap我需要它的方式)因此我决定采用该主题中的OP正在做的事情:获取一个列表并自己填充HashMap
。这将允许我通过映射获取对象,只需少量代码,就可以填充必要的HashMap
。
答案 3 :(得分:0)
我曾经遇到过同样的问题。
正如@Andy Pryor建议你可以使用ResultHandler
。
但正如我刚才“拆分”你的数据一样。
我的意思是将您在Map
的数据移动到另一个类。然后将您的Set
与此新班级相关联。
<resultMap type="com.example.CustomCollection" id="CustomCollectionMapping">
<collection property="items" javaType="java.util.TreeSet"
ofType="com.example.NewCustomItem" select="selectCustomItems"/>
</resultMap>
注意,这里com.example.NewCustomItem
是新课程。你只需要为这个类编写一个mapper,它就可以了。
但如果你真的需要Map
使用ResultHandler
那么。