Результат группы в Списке, который является атрибутом в Mybatis (Mapper) и Java - PullRequest
0 голосов
/ 04 октября 2019

У меня есть вопрос о Mappers в Mybatis. У меня есть два класса, как это:

public class A{
  private String A1;
  private String A2;
  private List<B> listB;
  //getters and setters
  .
  .
  .
  public static class B {
   private String B1;
   private String B2;
   //getters and setters
   .
   .
   .

  }

}

Тогда у меня есть класс маппер, как это:

@Mapper
public interface ABMapper{

@Select("select b1,b2 from b where b.a1 = #{a1}")
public List<B> getBs(@Param("a1") String a1);

@Select ("select a1,a2 from a limit 100")
@Results({
@Result(property="a1", value = "a1"),
@Result(property="a2", value = "a2"),
@Result(property="listB", column="a1", many = @Many(select = "getBs"))
})
public List<A> getAs();
}

Это работает нормально, но я знаю, что когда getAs() выполняется, getBs запускаетсястолько раз, сколько предметов (например, предел 100). Интересно, что если существует способ выполнить запрос типа select a.a1,a.a2,b.b1,b.b2 from a a inner join b b on a.a1 = b.a1, а затем Mybatis (и Java) могут сгруппировать элементы в List<A>, а атрибут B не будет пустым. Возможно, в классе А и В нужно использовать хеш и равно, но я не знаю.

Спасибо за ваши ответы.

1 Ответ

1 голос
/ 07 октября 2019

Mybatis может сделать это, но только если вы используете отображение xml. Ограничение аннотаций в java делает невозможным сопоставление ассоциаций с объединением:

Вы заметите, что сопоставление объединений не поддерживается через API аннотаций. Это связано с ограничением в Java-аннотациях, которое не допускает циклические ссылки.

В этом случае отображение может выглядеть следующим образом:

<resultMap id="bMap" type="B">
  <id property="b1" column="b1"/>
  <result property="b2" column="b2"/>
</resultMap>

<resultMap id="aMap" type="A">
    <id property="a1" column="a1"/>
    <result property="a2" column="a2"/>
    <collection property="listB" javaType="B" resultMap="bMap" columnPrefix="b_"/>
</resultMap>

<select id='getAs' resultMap='aMap'>
SELECT a.*, b.id B_id, b.b1 B_b1, b.b2 B_b2
FROM (
   select *
   from a
   LIMIT 100
  ) AS a
  LEFT JOIN AS b on a.a1 = b.a1
</select>

Некоторые важные примечания:

  1. и A, и B должны иметь некоторые идентифицирующие поля, сконфигурированные с элементом id. Значение в этом поле будет использоваться для идентификации объекта и выполнения того, что вы называете группировкой. Для таблицы a это выглядит как a1 (так как вы использовали его в качестве поля соединения), и я использовал его в примере.
  2. autoMapping="true" в resultMap может быть полезно, если их многополя для сопоставления
  3. необходимо использовать левое / правое объединение для обработки тех записей из таблицы a, которые не имеют ничего в b.
  4. , чтобы LIMIT работалоправильно с объединением, вы должны сделать это для выбора, который получает записи из a, а не для результата объединения, иначе вы можете получить менее 100 записей в результате, если объединено более 100 записей из b.
  5. это зависит от варианта использования, но обычно, если вы используете LIMIT, вам нужно указать какой-то порядок, в противном случае записи будут возвращены в непредсказуемом порядке.
  6. В более старых версиях mybatis была ошибка, котораятребуется, чтобы префиксы столбцов в запросе были прописными (возможно, это исправлено, я не уверен).
...