#java #collections #mapping #persistence #mybatis
#java #Коллекции #сопоставление #постоянство #mybatis
Вопрос:
Я изучаю возможности сопоставления MyBatis 3.0.5. База данных находится в режиме H2 (1.3.160) в запущенном встроенном режиме. С помощью руководства пользователя я получил простые рабочие части. Но мне трудно сопоставить a Set
, который использует a HashMap
в качестве резервного хранилища.
Вот код Java для пользовательской коллекции, которая имеет настраиваемое поле set as (упрощенное для краткости)
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 framework:
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>
Через различные итерации я получил ошибку «слишком много результатов», какую-то другую ошибку или ничего (null возвращается из вызова mapper), но никогда не получал нужного мне результата. Код SQL отлично работает сам по себе, и если я запрошу список с помощью простого оператора select, я получу обратно строки и ArrayList . Проблема, с которой я сталкиваюсь, заключается в правильном заполнении вложенных объектов коллекции.
Я много раз читал руководство, искал примеры, но не мог найти правильный XML-файл сопоставления для этой цели. Я был бы признателен, если кто-нибудь сможет мне помочь или указать мне источник, который может помочь.
Заранее спасибо за всю помощь.
Ответ №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
}
]
}
]
}
]
Ответ №2:
Возможно, вы захотите попробовать пользовательский обработчик результатов. Я думаю, что ваш пользовательский набор должен работать. Я собираюсь продолжить расследование, я обновлю, если что-то найду.
Ответ №3:
Похоже ResultHandler
, это может сработать, но это заставляет меня писать много кода, оставляя преимущества фабрики сопоставления XML. Также меня беспокоит тот факт, что обработчик будет вызываться один раз для каждой возвращаемой строки.
Я узнал из сообщения в группе пользователей mybatis, что Mybatis на самом деле не будет делать то, что я хочу (даже если я избавлюсь от посредника CustomSet
, не похоже, что Mybatis сможет заполнить hashmap так, как мне нужно), поэтому я решил пойти с тем, что ОПв этой теме делается следующее: получение списка и заполнение самого HashMap
себя. Это позволит мне получать объекты через сопоставление и с небольшим количеством кода HashMap
заполнять необходимые данные.
Ответ №4:
однажды у меня была такая же проблема. Как предлагает @Andy Pryor, вы можете использовать ResultHandler
. Но, как я только что «разделил» ваши данные.
Я имею в виду переместить ваши данные, которые будут находиться в a 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
тогда.