文章

pg数据库到达梦8迁移适配-数组集合运算

pg数据库到达梦8迁移适配-数组集合运算

pg数据库到达梦8迁移适配-数组集合运算

pg实现

在pg数据库中,运算符<@表示被包含集合运算符,类似的还有@>包含运算等。

1
2
-- pg sql例
select * from tb_xx where ARRAY[#{indexCode}] ::_text <@ index_codes;

适配达梦

达梦数据库中没有类似的运算符。可以使用自定义二元运算符来实现。也可自定义数组类型,和使用MULTISET集合运算函数一起实现该功能,需要改写sql,同时在dao层自定义类型处理器。

sql定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
--dm8 sql

-- 使用dm的嵌套表,自定义数组类型DM_ARRAY,实现pg数组的集合比较
CREATE or REPLACE TYPE DM_ARRAY is table of VARCHAR;

-- 包含,相当于pg的@> 使用MULTISET做集合交集运算
CREATE OR REPLACE FUNCTION f_array_is_include(s1 IN DM_ARRAY, 
                                              s2 IN DM_ARRAY)
    RETURN INT AS s3 DM_ARRAY;
    v_rs   INT;
    BEGIN
        s3 := s1 MULTISET INTERSECT s2;
        IF s3.COUNT = s2.COUNT THEN
            v_rs := 1;
        ELSE
            v_rs:= 0;
        END IF;
        RETURN v_rs;
    END;

-- 被包含,相当于pg的<@ 使用MULTISET做集合交集运算
CREATE OR REPLACE FUNCTION f_array_is_be_include(s1 IN DM_ARRAY, 
                                                 s2 IN DM_ARRAY)
    RETURN INT AS s3 DM_ARRAY;
    v_rs   INT;
    BEGIN
        s3 := s1 MULTISET INTERSECT s2;
        IF s3.COUNT = s1.COUNT THEN
            v_rs := 1;
        ELSE
            v_rs:= 0;
        END IF;
        RETURN v_rs;
    END;

-- 相等比较,相当于= 使用MULTISET做集合差集运算
CREATE OR REPLACE FUNCTION f_array_is_equal(s1 IN DM_ARRAY, 
                                            s2 IN DM_ARRAY)
    RETURN INT AS s3 DM_ARRAY;
    v_rs   INT;
    BEGIN
        IF s1.COUNT <> s2.COUNT THEN
            v_rs := 0;
        ELSE
            s3 := s1 MULTISET EXCEPT s2;
            IF s3.COUNT = 0 THEN
                v_rs := 1;
            ELSE
                v_rs:= 0;
            END IF;
        END IF;
        RETURN v_rs;
    END;

-- test
/*
select f_array_is_include(DM_ARRAY('qwe','asd'), DM_ARRAY('asd','qwe'));
select f_array_is_be_include(DM_ARRAY('qwe','asd'), DM_ARRAY('asd','qwe','ddd'));
select f_array_is_equal(DM_ARRAY('qwe','asd'), DM_ARRAY('asd','qwe'));
*/

应用层java自定义类型处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.xxx;

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

import java.sql.*;

/**
 * dao层自定义类型处理器
 */
@MappedTypes(Object[].class)
public class DmArrayTypeHandler extends BaseTypeHandler<Object[]> {

    /**
     * 自定义类型名
     */
    private static final String TYPE_NAME_CTM = "DM_ARRAY";

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object[] parameter, JdbcType jdbcType) throws SQLException {
        Connection conn = ps.getConnection();
        Array array = conn.createArrayOf(TYPE_NAME_CTM, parameter);
        ps.setArray(i, array);
    }

    @Override
    public Object[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // TODO
        return new Object[0];
    }

    @Override
    public Object[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        // TODO
        return new Object[0];
    }

    @Override
    public Object[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        // TODO
        return new Object[0];
    }
}

应用层java mapper中使用自定义类型处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxx.dao.DemoDao">
    <resultMap type="DemoResult" id="DemoResultMap">
        <result property="indexCodes" column="index_codes" jdbcType="ARRAY"
                typeHandler="com.xxx.DmArrayTypeHandler"/>
    </resultMap>

    <insert id="add" parameterType="DemoResult">
        insert into tb_xxx (index_codes)
        values (#{indexCodes,typeHandler=com.xxx.DmArrayTypeHandler})
    </insert>
</mapper>
本文由作者按照 CC BY 4.0 进行授权