为了账号安全,请及时绑定邮箱和手机立即绑定

mybatis中如何选择文本数组类型的结果?

mybatis中如何选择文本数组类型的结果?

慕码人8056858 2022-11-02 16:58:08
例如text[],在 PostgreSQL 中有一个表,它的列类型为 :CREATE TABLE t(    id integer,    name text,    tags text[],    PRIMARY KEY (id))现在,我想通过tags两种方式进行选择:tags使用主键选择id,结果应该是类型List<String>选择tagsusing name,结果应该是 typeList<List<String>>我应该如何编写 MyBatis 映射器来实现这一点?
查看完整描述

2 回答

?
蛊毒传说

TA贡献1895条经验 获得超3个赞

你仍然可以使用 Java 映射器,但是,SqlSession#selectList当返回类型是List并且这不是你想要的时,MyBatis 会在内部调用。

因此,您需要改为使用Object作为返回类型。


@Select("select tags from t where id = #{id}")

Object getTagById(Integer id);


@Select("select tags from t where name = #{name}")

List<Object> getTagByName(String name);

并在配置中全局注册您的类型处理程序。IE


<typeHandlers>

  <typeHandler handler="xxx.yyy.ListArrayTypeHandler" />

</typeHandlers>

或者


configuration.getTypeHandlerRegistry()

  .register(ListArrayTypeHandler.class);

为了完整起见,这里是一个示例类型处理程序实现。


import java.sql.Array;

import java.sql.CallableStatement;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;


import org.apache.ibatis.type.BaseTypeHandler;

import org.apache.ibatis.type.JdbcType;

import org.apache.ibatis.type.MappedJdbcTypes;

import org.apache.ibatis.type.MappedTypes;


@MappedJdbcTypes({ JdbcType.ARRAY })

@MappedTypes({ Object.class })

public class ListArrayTypeHandler extends BaseTypeHandler<List<?>> {


  @Override

  public void setNonNullParameter(PreparedStatement ps, int i,

      List<?> parameter, JdbcType jdbcType) throws SQLException {

    //  JDBC type is required

    Array array = ps.getConnection().createArrayOf("TEXT", parameter.toArray());

    try {

      ps.setArray(i, array);

    } finally {

      array.free();

    }

  }


  @Override

  public List<?> getNullableResult(ResultSet rs, String columnName) throws SQLException {

    return extractArray(rs.getArray(columnName));

  }


  @Override

  public List<?> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {

    return extractArray(rs.getArray(columnIndex));

  }


  @Override

  public List<?> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {

    return extractArray(cs.getArray(columnIndex));

  }


  protected List<?> extractArray(Array array) throws SQLException {

    if (array == null) {

      return null;

    }

    Object javaArray = array.getArray();

    array.free();

    return new ArrayList<>(Arrays.asList((Object[])javaArray));

  }

}

仅供参考,要将 a 存储List到tags列中,您可能必须明确指定类型处理程序。


insert into t (...) values (#{id}, #{name},

  #{tags,typeHandler=xxx.yyy.ListArrayTypeHandler})


查看完整回答
反对 回复 2022-11-02
?
郎朗坤

TA贡献1921条经验 获得超9个赞

你不是第一个遇到这个问题的人。


项目common-mybatis有一个专门针对这个用例的类型处理程序:StringArrayTypeHandler


只需将其添加到 MyBatis 配置中:


    <typeHandlers>

        <typeHandler handler="org.gbif.mybatis.type.StringArrayTypeHandler"/>

    </typeHandlers>

...然后对于映射,它很简单:


    <select id="getTagsById" resultType="java.util.List">

        SELECT tags FROM t WHERE id = #{id}

    </select>


    <select id="getTagsByName" resultType="java.util.List">

        SELECT tags FROM t WHERE name = #{name}

    </select>

...在代码中:


try (SqlSession session = sessionFactory.openSession()) {

    List<String> tags = session.selectOne("[...].getTagsById", 1);

    System.out.println("Tags: " + tags);


    List<List<String>> multiTags = session.selectList("[...].getTagsByName", "test");

    System.out.println("Tags: " + multiTags);

}

使用 JDBC 驱动程序版本 42.2.5 和以下测试数据针对 PostgreSQL 11 进行测试:


select * from t;

 id |  name   |                tags                

----+---------+------------------------------------

  1 | test    | {Thriller,Drama}

  2 | my name | {Science-Fiction,Adventure,Horror}

  3 | test    | {Comedy,Adventure}

(3 rows)

...产生:


Tags: [Thriller, Drama]

Tags: [[Thriller, Drama], [Comedy, Adventure]]


查看完整回答
反对 回复 2022-11-02
  • 2 回答
  • 0 关注
  • 75 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信