Как установить аргумент в маппере myBatis от другого маппера - PullRequest
0 голосов
/ 31 октября 2018

У меня есть некоторые проблемы с отображением в myBatis.

У меня есть класс pojo

public class Video {
    private int id;
    private String title;
    private Set<Person> actors;
    ...
    getters & setters
}

У меня есть интерфейс PersonMapper

public interface PersonMapper {
@Select("${query}")
    Set<Person> getByFilmId(@Param("id") long id, @Param("query") PersonByFilmQueries query);

enum PersonByFilmQueries {

        ACTORS_BY_FILM(
                "select " +
                "   * " +
                "from " +
                "   actors a, " +
                "   film_actors fa " +
                "where " +
                "   fa.actor_id = a.id " +
                "and fa.film_id = #{id}"),
        ....
        WRITERS_BY_FILM(
                "select "+
                "* " +
                "from " +
                "writers w, " +
                "film_writers fw " +
                "where " +
                "fw.writer_id = w.id " +
                "and fw.film_id = #{id}");
        private String query;

        PersonByFilmQueries(String query) {
            this.query = query;
        }

        @Override
        public String toString() {
            return query;
        }
    }
}

Я пытаюсь повторно использовать этот выбор из другого картографа xml (VideoMapper.xml).

<mapper namespace="ru.common.mapper.VideoMapper">
    <resultMap id="video" type="Video">
    <id property="id" column="id"/>
    <result property="title" column="title"/>
    </resultMap>
    <collection property="actors" javaType="HashSet" ofType="Person" column="id" 
    select="ru.common.mapper.PersonMapper.getByFilmId">
    </collection>
</resultMap> 

Я пытаюсь добавить коллекцию Person в видео POJO. Но я не понимаю, как установить второй аргумент в перечислении getByFilmId с sql. Есть ли простой способ сделать это? Если я вызываю этот маппер из Java, то проблем нет, все работает

1 Ответ

0 голосов
/ 01 ноября 2018

В общем случае вы можете указать несколько параметров для вложенного выбора для ассоциации или коллекции.

Если бы параметры query были простой строкой (а не перечислением), вы можете добавить столбец к основному запросу, который возвращает список видео, например:

select id, title, ..., 'ACTORS_BY_FILM' query_type
from video

Затем вы изменяете отображение для коллекции:

 <collection property="actors" javaType="HashSet" ofType="Person" column="{id=id,query=query_type}" 
select="ru.common.mapper.PersonMapper.getByFilmId">

Таким образом, столбцы id и query_type из основного запроса будут переданы как параметры для вложенного выбора.

В вашем случае вам нужно, чтобы mybatis вызывал конструктор для переданного строкового параметра, и я не думаю, что mybatis это поддерживает.

Один из способов, которым вы можете попытаться преодолеть это. Я не уверен, что это сработает, поскольку вы уже находитесь на серой территории, когда используете двойную замену. Я бы сказал, что это не намеренное поведение mybatis.

Но вы можете попробовать. Так что измените метод маппера, чтобы он принимал строку.

Затем вы можете создать вспомогательный статический метод, который преобразует имя запроса в текст запроса:

 public class PersonByFilmQueryBuilder {

     public static String getQuery(String queryId) {
          return PersonByFilmQueries.valueOf(queryId);
     }
 }

Теперь вы можете использовать этот статический метод в выражении OGNL в select следующим образом:

@Select("${@com.mycompany.myapp.PersonByFilmQueryBuilder@getQuery(query)}")
Set<Person> getByFilmId(@Param("id") long id, @Param("query") String query);

Я не совсем уверен, что на этом этапе генерации запросов mybatis использует полнофункциональное выражение OGNL. Если это произойдет, это будет работать.

...