Пример отображения вложенной коллекции Mybatis 3.0.5 - PullRequest
2 голосов
/ 05 октября 2011

Я изучаю возможности картографирования 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), но никогда результат, который мне нужен. Код SQL работает сам по себе, и если я попрошу List с простым оператором select, я получу строки и ArrayList. У меня проблема с заполнением вложенных объектов коллекции.

Я много раз читал руководство, искал примеры, но не смог придумать правильный XML-код для этой цели. Буду признателен, если кто-нибудь сможет мне помочь или укажет на источник, который может помочь.

Заранее спасибо за помощь.

Ответы [ 4 ]

1 голос
/ 21 ноября 2015

Это мой рабочий пример:

<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
            }
          ]
        }
      ]
    }
  ]
0 голосов
/ 08 октября 2011

Похоже, что ResultHandler может сработать, но это оставляет меня писать много кода, оставляя преимущества фабрики отображения XML. Также меня беспокоит тот факт, что обработчик будет вызываться один раз для каждой возвращаемой строки.

Я обнаружил в сообщение в группе пользователей mybatis , что Mybatis на самом деле не будет делать то, что я хочу (даже если я избавлюсь от посредника CustomSet, это не похоже на Mybatis иметь возможность заполнять хэш-карту так, как мне нужно), поэтому я решил остановиться на том, что делает OP в этой теме: вернуть список и заполнить HashMap самостоятельно. Это позволит мне получить объекты через отображение и с небольшим количеством кода, заполнить необходимые HashMap.

0 голосов
/ 08 ноября 2015

однажды у меня была такая же проблема. Как @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 - это новый класс. Вам просто нужно написать еще один маппер для этого класса, и он работает.

Но если вам действительно нужно иметь Map, используйте ResultHandler, тогда.

0 голосов
/ 05 октября 2011

Возможно, вы захотите попробовать пользовательский ResultHandler .Я думаю, однако, ваш CustomSet должен работать.Я собираюсь исследовать дальше, я буду обновлять, если я найду что-то.

...