java Mybatis 3.0.5 嵌套集合映射示例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7663585/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mybatis 3.0.5 nested collection mapping Example
提问by alokoko
I am investigating the mapping facilities of MyBatis 3.0.5. The database is H2 (1.3.160) in running embedded mode. With the help of the user manual, I got the straightforward parts working. But I am having a hard time mapping a Set
that uses a HashMap
as the backing storage.
我正在研究 MyBatis 3.0.5 的映射工具。数据库是运行嵌入模式的 H2 (1.3.160)。在用户手册的帮助下,我得到了简单的部分。但是我很难映射Set
使用 aHashMap
作为后备存储的 a 。
Here's the Java code for the custom collection that has the custom set as field (simplified for brevity)
这是具有自定义设置为字段的自定义集合的 Java 代码(为简洁起见进行了简化)
public class CustomCollection
{
@JsonProperty
private CustomSet<CustomItem> customItems;
public CustomCollection()
{
customItems = new CustomSet<CustomItem>();
}
// other stuff
}
Here's the CustomSet
code (again, simplified)
这是CustomSet
代码(再次简化)
public class CustomSet<E extends CustomItemInterface> extends AbstractSet<E>
{
private ConcurrentHashMap<String, E> items;
public CustomSet()
{
items = new ConcurrentHashMap<String, E>();
}
// other stuff
}
Here's the mapping interface:
映射界面如下:
public interface CustomCollectionMapper
{
CustomCollection select(@Param("somename") String s1, @Param("someothername") String s2);
}
This is the code that does the call into the Mybatis framework:
这是调用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();
}
Here's what I could come up with the mapping XML so far:
到目前为止,这是我可以想出的映射 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>
Through various iterations, I got "too many results" error, some other error or nothing (null is returned from the mapper call) but never the result I need. The SQL code works fine by itself and if I ask for a List with a straightforward select statement, I get the rows and the ArrayList back. The problem I am having is having the nested collection objects populated properly.
通过各种迭代,我得到了“结果太多”错误、其他一些错误或什么都没有(从映射器调用返回 null),但从来没有得到我需要的结果。SQL 代码本身运行良好,如果我使用简单的 select 语句请求 List,我会返回行和 ArrayList。我遇到的问题是正确填充了嵌套的集合对象。
I have read the manual many times, searched for examples but I could not come up with the correct mapping XML for this purpose. I would appreciate if anyone can help me or point me to a source that can help.
我已经多次阅读手册,搜索示例,但我无法为此目的想出正确的映射 XML。如果有人可以帮助我或向我指出可以提供帮助的来源,我将不胜感激。
Thanks in advance for all the help.
在此先感谢您的帮助。
回答by Sameer Kazi
This is my working example:
这是我的工作示例:
<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>
This is my query
这是我的查询
<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>
And output is:
输出是:
[
{
"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
}
]
}
]
}
]
回答by Andy
You may want to try a custom ResultHandler. I think though, your CustomSet should work. I'm going to investigate further, I will update if I find something.
您可能想尝试自定义ResultHandler。我认为,您的 CustomSet 应该可以工作。我会进一步调查,如果我发现了什么我会更新。
回答by alokoko
It looks like ResultHandler
may do the trick, but that leaves me writing a lot of code, leaving the benefits of the XML mapping factory. Also the fact that the handler will be called once per returned row is worrying me.
看起来ResultHandler
可能会奏效,但这让我编写了大量代码,而留下了 XML 映射工厂的好处。此外,每个返回的行都会调用一次处理程序这一事实也让我感到担忧。
I found out in a message in the mybatis-user groupthat Mybatis will not actually do what I want (even if I get rid of the intermediary CustomSet
, it does not look like Mybatis will be able to populate the hashmap the way I need it) so I have decided to go with what the OP in that topic is doing: Getting back a list and populating the HashMap
myself. This will allow me to get the objects through the mapping and with little amount of code, have the necessary HashMap
populated.
我在 mybatis-user 组的一条消息中发现,Mybatis 实际上不会做我想做的事情(即使我摆脱了中介CustomSet
,看起来 Mybatis 也无法按照我需要的方式填充哈希图)所以我决定采用该主题中的 OP 正在做的事情:取回列表并填充HashMap
我自己。这将允许我通过映射获取对象,并用少量代码HashMap
填充必要的内容。
回答by Dmitry Dyokin
i had the same problem once.
As @Andy Pryor suggests you can use ResultHandler
.
But as i did just 'split' your data.
我曾经遇到过同样的问题。正如@Andy Pryor 建议的那样,您可以使用ResultHandler
. 但正如我所做的那样,只是“拆分”了您的数据。
I mean move your data that is going to be in a Map
to another class. And then associate your Set
with this new class.
我的意思是将您的数据移动Map
到另一个类中。然后将您的Set
与这个新类相关联。
<resultMap type="com.example.CustomCollection" id="CustomCollectionMapping">
<collection property="items" javaType="java.util.TreeSet"
ofType="com.example.NewCustomItem" select="selectCustomItems"/>
</resultMap>
Note, here com.example.NewCustomItem
is that new class. You just need to write one more mapper for this class and it works.
请注意,这com.example.NewCustomItem
是新课程。你只需要为这个类再写一个映射器就可以了。
But if your really need to have a Map
use ResultHandler
then.
但如果你真的需要Map
使用的ResultHandler
话。