MyBatis PostgreSQL实现数组类型的操作

我的GitHub:Powerveil · GitHub

我的Gitee:Powercs12 (powercs12) - Gitee.com

皮卡丘每天学Java

最近在学习数据库PostgreSQL,遇到如何实现对数组类型的数据操作,试着自己尝试学习实现。

话不多说,直接撸代码。

建表语句 PostgreSQL DDL

-- auto-generated definition
create table faviroute_book
(
    employee_id integer,
    books       integer[]
);

insert into faviroute_book values (1,ARRAY [1,2,55]);
insert into faviroute_book values (2,ARRAY [1,2,23]);
insert into faviroute_book values (3,ARRAY [1,23,554]);

select *
from faviroute_book;

备注:integer

 application.yml

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/test
    driver-class-name: org.postgresql.Driver
    username: postgres
    password: 123456

FavirouteBookMapper.xml需要的配置

<resultMap id="BaseResultMap" type="com.power.mytest.domain.FavirouteBook">
    <result property="employeeId" column="employee_id" jdbcType="INTEGER"/>
<!--        <result property="books" column="books" jdbcType="ARRAY" typeHandler="org.apache.ibatis.type.ArrayTypeHandler"/>-->
<!--这里使用resultMap会识别到,注意这里说的是mybatis/>-->
    <result property="books" column="books" jdbcType="ARRAY"
            typeHandler="com.power.mytest.handler.ArrayTypeHandler"/>
</resultMap>


<insert id="insertFavirouteBook" parameterType="com.power.mytest.domain.FavirouteBook">
    INSERT INTO faviroute_book (employee_id, books)
    VALUES (#{employeeId}, #{books, jdbcType=ARRAY, typeHandler=com.power.mytest.handler.ArrayTypeHandler})
</insert>

以插入和查询单个为例

FavirouteBookMapper.java

@Mapper
public interface FavirouteBookMapper extends BaseMapper<FavirouteBook> {

    int insertFavirouteBook(FavirouteBook favirouteBook);

    FavirouteBook getOneByIdMy(Integer id);
}

插入方法时需要加上jdbcType=ARRAY, typeHandler=org.apache.ibatis.type.ArrayTypeHandler

typeHandler是一个数组类型转换器,

查询方法时,resultMap的数组字段要加上jdbcType=ARRAY, typeHandler=org.apache.ibatis.type.ArrayTypeHandler

这里我使用的是apache的

也可以使用自定义,当然apache更全,下面是一个自定义的数组类型转换器

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeException;

import java.sql.*;

public class ArrayTypeHandler extends BaseTypeHandler<Object[]> {
    private static final String TYPE_NAME_VARCHAR = "varchar";
    private static final String TYPE_NAME_INTEGER = "integer";
    private static final String TYPE_NAME_BOOLEAN = "boolean";
    private static final String TYPE_NAME_NUMERIC = "numeric";
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object[] parameter, JdbcType jdbcType) throws SQLException {
        String typeName = null;
        if (parameter instanceof Integer[]) {
            typeName = TYPE_NAME_INTEGER;
        } else if (parameter instanceof String[]) {
            typeName = TYPE_NAME_VARCHAR;
        } else if (parameter instanceof Boolean[]) {
            typeName = TYPE_NAME_BOOLEAN;
        } else if (parameter instanceof Double[]) {
            typeName = TYPE_NAME_NUMERIC;
        }
        if (typeName == null) {
            throw new TypeException("ArrayTypeHandler parameter typeName error, your type is " + parameter.getClass().getName());
        }
        // 这3行是关键的代码,创建Array,然后ps.setArray(i, array)就可以了
        Connection conn = ps.getConnection();
        Array array = conn.createArrayOf(typeName, parameter);
        ps.setArray(i, array);
    }
    @Override
    public Object[] getNullableResult(ResultSet resultSet, String s) throws SQLException {
        return getArray(resultSet.getArray(s));
    }
    @Override
    public Object[] getNullableResult(ResultSet resultSet, int i) throws SQLException {
        return getArray(resultSet.getArray(i));
    }
    @Override
    public Object[] getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        return getArray(callableStatement.getArray(i));
    }
    private Object[] getArray(Array array) {
        if (array == null) {
            return null;
        }
        try {
            return (Object[]) array.getArray();
        } catch (Exception e) {
        }
        return null;
    }
}

对应的xml

<insert id="insertFavirouteBook" parameterType="com.power.mytest.domain.FavirouteBook">
    INSERT INTO faviroute_book (employee_id, books)
    VALUES (#{employeeId}, #{books, jdbcType=ARRAY, typeHandler=org.apache.ibatis.type.ArrayTypeHandler})
</insert>

<select id="getOneByIdMy" resultMap="BaseResultMap">
    select * from faviroute_book
    where employee_id = #{id}
</select>

测试类

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {MyTestApplication.class})
public class Test01 {

    @Autowired
    private FavirouteBookService favirouteBookService;

    @Test
    public void test02() {
        FavirouteBook favirouteBook = new FavirouteBook();
        Integer[] arrays = new Integer[] {43,123,321};
        favirouteBook.setEmployeeId(100);
        favirouteBook.setBooks(arrays);
        favirouteBookService.insertFavirouteBook(favirouteBook);
    }


    @Test
    public void test03() {
        FavirouteBook oneByIdMy = favirouteBookService.getOneByIdMy(1);
        System.out.println(oneByIdMy);
    }
}

效果

插入

 

查询

如果要使用MyBatis Plus查询,而且使用内置的方法就不可以了

测试方法

@Test
public void test01() {
    System.out.println("Hello World");
    System.out.println("==============使用list()方法====================");
    List<FavirouteBook> list = favirouteBookService.list();
    System.out.println(list);
    System.out.println("==============使用getOne()方法====================");
    LambdaQueryWrapper<FavirouteBook> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(FavirouteBook::getEmployeeId, 1);
    FavirouteBook favirouteBook = favirouteBookService.getOne(queryWrapper);
    System.out.println(favirouteBook);
    System.out.println(Arrays.toString(favirouteBook.getBooks()));
}

效果

怎么解决呢?

需要在实体类中加入一些配置,必须加入的有

autoResultMap = true

@TableField(value = "books", jdbcType = JdbcType.ARRAY, typeHandler = ArrayTypeHandler.class)

@TableName(value ="faviroute_book", autoResultMap = true)
@Data
public class FavirouteBook implements Serializable {
    @TableField(value = "employee_id")
    private Integer employeeId;
    @TableField(value = "books", jdbcType = JdbcType.ARRAY, typeHandler = ArrayTypeHandler.class)
    private Integer[] books;
}

为了让框架识别通过实体类加过直接生成的resultMap,框架默认识别不了我们自己写的resultMap

查看效果

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis中,当需要返回数组类型时,可以使用以下两种方式进行配置。 第一种方式是使用resultMap,通过在Mapper.xml中定义resultMap,将查询结果的字段映射到实体类的属性上。可以使用<result>标签指定属性名、数据库字段名和类型处理器。例如: <resultMap type="返回实体类" id="result"> <result property="实体类字段名" column="mysql字段名" typeHandler="处理类"/> </resultMap> <select id="Mapper.java的方法名" parameterType="传参类型" resultMap="resultMap的id"> select pricture from xm_picture </select> 第二种方式是使用注解,通过在Mapper接口中使用@Select注解直接编写SQL语句,并使用@Results注解进行属性和字段的映射。例如: @Select("<script>" "select picture from xm_picture where id = #{id}" "</script>") @Results({@Result(property="实体类字段名", column="数据库字段名", typeHandler=处理类.class)}) PictureDto selectById(Long id); 以上是关于MyBatis返回数组类型的两种方法和配置示例。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Mybatis的返回参数类型](https://blog.csdn.net/hyj_king/article/details/95983495)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Mybatis 返回数组 两种方式](https://blog.csdn.net/Aa_duidui/article/details/119947313)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值