扩展JPA对数组字段的支持(postgresql数据库)

扩展JPA对postgresql数据库数组字段的支持

此内容代码并未完全贴出来,代码码云地址:https://gitee.com/daifylearn/postgresql

postgresql虽然支持数组字段,但是Hibernate却不支持,这里需要特殊处理

直接使用三方依赖

直接引入Hibernate大佬Vlad Mihalcea自己写的开源库,轻松愉快

引入依赖

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-52</artifactId>
    <version>2.9.10</version>
</dependency>

自己实现

适用于有特殊的业务的需求或者不方便引入其他依赖的情况。主要代码还是依赖于Vlad Mihalcea的开源库。大佬已经完成代码实现,我们只需要抄就是了。
当然我们没必要把所有内容都抄一边,只抄自己需要的部分就可以主要涉及三部分代码:

需要自己实现的代码

这一块的代码主要在com.hi.config.array包内

主要接口或类的作用

JavaTypeDescriptor:JAVA对数据的描述,此接口提供了java方向值映射的描述内容。扩展的时候可以直接依赖抽象类AbstractTypeDescriptor
SqlTypeDescriptor:JDBC对数据的处理,提供了一些值绑定、折叠等功能。
AbstractSingleColumnStandardBasicType:双方桥梁的基础数据类型的定义,其是一个接口集包含了众多接口SingleColumnType,BasicType,
StringRepresentableType,ProcedureParameterExtractionAware,ProcedureParameterNamedBinder。主要提供了对基础数据类型的值绑定等操作,
当然大部分内容在AbstractSingleColumnStandardBasicType中已经有部分实现,节省了很多自己实现的动作。

使用demo

这里是使用了hibernate-types-52的操作方式,当然自己实现的时候也是一样的内容

添加依赖

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-52</artifactId>
    <version>2.9.10</version>
</dependency>

数据模型新建

java数据模型

@Data
@Entity
@TypeDefs({
        @TypeDef(name = "string-array",typeClass = StringArrayType.class)
})
public class ArrayBean {

    @Id
    @Column(name = "id")
    private String id;

    @Column(name = "name")
    private String name;

    @Type(type = "string-array")
    @Column(columnDefinition = "text[]")
    private String[] authorName;
}

在实体对象类上需要声明使用的特殊类型的名称和对应类@TypeDef,在对应属性上使用@Type声明类型名称,同时指定数组内元素类型columnDefinition

生成的建表语句

CREATE TABLE public.array_bean (
	id varchar(255) NOT NULL,
	author_name text[] NULL,
	"name" varchar(255) NULL,
	CONSTRAINT array_bean_pkey PRIMARY KEY (id)
)
WITH (
	OIDS=FALSE
) ;

数据查询

JPA格式

这个是用可以使用JPA命名规则来实现相关查询。但是需要注意,JPA并不能很好的完成数组字段的筛选和判断。

public interface ArrayBeanRepository extends JpaRepository<ArrayBean,String> {

    List<ArrayBean> findByAuthorName(String[] authorName);
}

上面的方法转化为SQL等价于下面的内容,只能进行简单的等于、不等于判断。

SELECT * FROM public.array_bean x
where array['a','b'] = x.author_name

这里需要严格匹配不仅对数组对象的元素值进行严格匹配,对顺序需要一致。但是很多时候对于数组内的数据,而postgresql针对数组参数的筛选有更加丰富的语法,
所以如果我们希望有更加灵活的方式来进行匹配。这里需要使用原生SQL来实现相关内容。

使用@Query在方法中使用原生SQL

    /**
     * @param authorName
     * @return
     */
    @Query(value = "SELECT * FROM public.array_bean x where CAST(string_to_array(?1,',') as text[]) && x.author_name",nativeQuery = true)
    List<ArrayBean> findByAuthorNameIn2(String authorName);

使用EntityManager进行原生SQL查询

@Service
public class ArrayBeanServiceImpl {

    @Autowired
    private EntityManager em;

    public List findArrayBeanByAuthorNameIn(List<String> authorName) {
        StringBuffer sql = new StringBuffer("SELECT * FROM public.array_bean x");
        String ids = authorName.stream().map(item -> "'" + item + "'").collect(Collectors.joining(","));
        sql.append(" where CAST(array[").append(ids).append("] as text[]) && x.author_name");
        Query query = em.createNativeQuery(sql.toString(),ArrayBean.class);
        List<ArrayBean> resultList = query.getResultList();
        ArrayBean arrayBean = resultList.get(0);
        System.out.println(arrayBean.getAuthorName());
        return resultList;
    }
}

上面两种方式都可以实现类似查询

SELECT * FROM public.array_bean x where CAST(string_to_array('a,b,c',',') as text[]) && x.author_name

不过使用@Query方式在某些SQL中进行值替换的时候需要将数组类型转换为字符串类型进行处理。

postgresql数组类字段的支持

数组间的判断

符号作用例子返回值详细介绍
=等于ARRAY[1,2,3]::int[] = ARRAY[1,2,3]true等于判断需要两个数组在内容上和顺序上严格相同
<>不等于ARRAY[1,2,3] <> ARRAY[1,2,4]true和=判断相反
<小于ARRAY[1,2,3] < ARRAY[1,2,4]true根据数组元素进行依次判断每个元素大小
>大于ARRAY[1,4,3] > ARRAY[1,2,4]true根据数组元素进行依次判断每个元素大小
<=小于或等于ARRAY[1,2,3] <= ARRAY[1,2,3]true根据数组元素进行依次判断每个元素大小
>=大于或等于ARRAY[1,4,3] >= ARRAY[1,4,3]true根据数组元素进行依次判断每个元素大小
@>包含ARRAY[1,4,3] @> ARRAY[3,1]true右侧元素中要全部出现在左侧中,对于右侧重复的元素并不要求个数相同,如:ARRAY[1,4,3] @> ARRAY[3,1,1] 也会返回true
<@被包含于ARRAY[2,7] <@ ARRAY[1,7,4,2,6]true和@>相反,需要左侧元素都出现在右侧
&&重叠(有共同元素)ARRAY[1,4,3] && ARRAY[2,1]true左右两侧有相同的元素存在

数组的操作

数组中添加元素使用 ||。根据双方数据类型不同会出现三种结果

数组值合并

当两个数组使用||时,会将其内容进行合并:

ARRAY[1,2,3] || ARRAY[4,5,6] -> {1,2,3,4,5,6}

作为数组子元素添加

如果一方是二维数组的时候,根据双方位置会将,数组添加至二维数组的头节点或者尾节点

ARRAY[1,2,3] || ARRAY[[4,5,6],[7,8,9]] -> {{1,2,3},{4,5,6},{7,8,9}}

值添加进数组中

根据值位于左侧或者右侧,单一值会作为数组的头部或尾部节点添加进来

ARRAY[4,5,6] || 7 -> {4,5,6,7}

数组相关函数

函数参数作用语法对应操作符结果
array_appendarray,element向数组尾部添加元素array_append(ARRAY[1,2], 3)||{1,2,3}
array_prependelement,array向数组头部添加元素array_append(3,ARRAY[1,2])||{3,1,2}
array_catarray,array合并两个数组元素array_cat(ARRAY[1,2,3], ARRAY[4,5])||{1,2,3,4,5}
array_dimsarray用来返回数组的上届和下届,当是多维数组的时候会依次显示其范围(下界默认1开始)array_dims(ARRAY[[1,2,3], [4,5,6]])[1:2][1:3]
array_lowerarray,int(数组的维数)返回指定维数的下界array_lower(ARRAY[[1,2,3], [4,5,6]],2)1
array_upperarray,int(数组的维数)返回指定维数的上界array_upper(ARRAY[1,2,3,4], 1)4
array_to_stringarray,text使用指定的分隔符将数组转换为字符串array_to_string(ARRAY[1, 2, 3], ‘,’)1,2,3
string_to_arraytext…将指定的字段将字符串切分为数组select string_to_array(‘a-b-c’,’-’)ARRAY[‘a’,‘b’,‘c’]{a,b,c}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大·风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值