如何通过另一个映射器在myBatis映射器中设置参数

时间:2018-10-30 21:44:44

标签: java orm mybatis ibatis

我的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的集合添加到Video POJO。 但是我不明白如何使用sql在g​​etByFilmId枚举中设置第二个参数。 有没有简单的方法可以做到这一点? 如果我从Java调用此映射器,那么就没有问题,一切正常

1 个答案:

答案 0 :(得分:1)

通常,您可以为关联或集合的嵌套选择指定多个参数。

如果query参数是简单的String(而不是枚举),则可以在主查询中添加一列,以返回如下所示的视频列表:

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">

这样,主查询中的列idquery_type将作为参数传递给嵌套的select。

在您的情况下,您需要mybatis在传递的字符串参数上调用构造函数,而我认为mybatis不支持此功能。

您可以尝试克服此问题的一种方法。我不确定它会起作用,因为使用双重替换时您已经处于灰色地带。我会说这不是mybatis的预期行为。

但是您可以尝试。因此,更改mapper方法以接受字符串。

然后,您可以创建一个辅助静态方法,该方法将查询的名称转换为查询文本:

 public class PersonByFilmQueryBuilder {

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

现在,您可以像这样在select中的OGNL表达式中使用此静态方法:

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

我不太确定在查询生成的这一阶段,mybatis是否会使用完整的OGNL表达式。如果可以,那么就可以。