如何使用JPA和Hibernate映射Java/Kotlin字符串数组和PostgreSQL SQL数组。

huangapple go评论79阅读模式
英文:

How to map Java/Kotlin string array and Postgres SQL array with JPA and hibernate

问题

@ElementCollection
@Column(name = "categories")
var categories: List<String>? = emptyList()
英文:

I have a field in Postgres in array type:

 categories    | text[]         |           |          |

How can I declare the field in the entity class?

I have tried below in Product.kt file but it throws error [ERROR]:ERROR: relation &quot;product_categories&quot; does not exist

@ElementCollection
@Column(name = &quot;categories&quot;)
var categories: List&lt;String&gt;? = emptyList()

My purpose is to save the string array as one field of the entity, I am not trying to do anything related "One to Many".

If you know any Java version solution and it works, I will accept the answer as well. Thanks

答案1

得分: 4

以下是翻译好的部分:

Adam的答案适用于使用Java编写的项目。由于我的项目是使用Kotlin编写的,我在下面分享我的版本,希望它能帮助到大家,使人们能够立即使用,而不必花时间转换:

有用的资源:如何在JPA和Hibernate中映射Java和SQL数组

Postgres:

alter table product add column categories text[];

Gradle:

implementation("com.vladmihalcea:hibernate-types-52:2.10.0")

Product.kt:

import com.vladmihalcea.hibernate.type.array.StringArrayType
import org.hibernate.annotations.*
import javax.persistence.*
import javax.persistence.Entity

@TypeDefs(
    TypeDef(name = "string-array", typeClass = StringArrayType::class)
)
@Entity
class Product(
        var name: String,

        @Type(type = "string-array")
        @Column(name = "categories", columnDefinition = "text[]")
        var categories: Array<String>? = arrayOf(),
)

Java和Kotlin之间有两个区别:

  1. Kotlin中的数组类型是Array,而不是String[],我也尝试过List,但不起作用。
  2. TypeDefs和TypeDef是不同的,在Kotlin中不需要@符号。
英文:

Adam's answer works for projects written in Java. As my project is written in Kotlin, I share my version below and hope it helps and people can use it right away other than spending time to convert:

Useful resource: How to map Java and SQL arrays with JPA and Hibernate

Postgres:

alter table product add column categories text[];

Gradle:

implementation(&quot;com.vladmihalcea:hibernate-types-52:2.10.0&quot;)

Product.kt

import com.vladmihalcea.hibernate.type.array.StringArrayType
import org.hibernate.annotations.*
import javax.persistence.*
import javax.persistence.Entity


@TypeDefs(
    TypeDef(name = &quot;string-array&quot;, typeClass = StringArrayType::class)
)
@Entity
class Product(
        var name: String,

        @Type(type = &quot;string-array&quot;)
        @Column(name = &quot;categories&quot;, columnDefinition = &quot;text[]&quot;)
        var categories: Array&lt;String&gt;? = arrayOf(),
)

There're 2 differences between Java and Kotlin:

  1. The array type in Kotlin is Array&lt;String> other than String[], I tried List&lt;String> as well but it didn't work.
  2. TypeDefs,TypeDef is different, no @ sign.

答案2

得分: 2

这将无法与@ElementCollection一起使用,因为它将始终尝试使用另一个表。您需要的是一个自定义类型。为此,您将需要以下依赖项:

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-52</artifactId>
    <version>${hibernate-types.version}</version>
</dependency>

然后,您可以定义自己的类型:

import com.vladmihalcea.hibernate.type.array.StringArrayType

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

    @Type( type = "string-array" )
    @Column(
        name = "categories", 
        columnDefinition = "character varying[]"
    )
    var categories: Array<String>
}

不过我还没有尝试过在List上使用这个,因为它映射到了一个Array。更多信息可以在这个答案中找到。

英文:

This won't work with @ElementCollection as it will always try to use another table. What you need is a custom type instead. For this you'll need this dependency:

&lt;dependency&gt;
    &lt;groupId&gt;com.vladmihalcea&lt;/groupId&gt;
    &lt;artifactId&gt;hibernate-types-52&lt;/artifactId&gt;
    &lt;version&gt;${hibernate-types.version}&lt;/version&gt;
&lt;/dependency&gt;

then you can define your own types:


import com.vladmihalcea.hibernate.type.array.StringArrayType

@TypeDefs({
    @TypeDef(
        name = &quot;string-array&quot;, 
        typeClass = StringArrayType.class
    )
})
@Entity
class YourEntity {

    @Type( type = &quot;string-array&quot; )
    @Column(
        name = &quot;categories&quot;, 
        columnDefinition = &quot;character varying[]&quot;
    )
    var categories: Array&lt;String&gt;;
}

I haven't tried this with a List though, as this maps to an Array. More info in this answer.

答案3

得分: 0

除了海峰提到的方法外,在Kotlin中,还有另一种选择,可以使用ListArrayType代替StringArrayType,这样您就不需要担心将列表转换为数组。

在检索数据时,我遇到了另一个问题,报告了java.lang.ArrayStoreException: arraycopy: type mismatch: can not copy [Ljava.lang.String;[] into java.lang.String[]\n。针对那些可能遇到类似问题的人,我的问题是数据库中存储的数据不是数组,而是数组的数组。

英文:

Apart from the one mentioned by Haifeng, for Kotlin, there is another option to use ListArrayType instead of StringArrayType so you do not need to care about converting list to array.

I met another issue retrieving the data, I had java.lang.ArrayStoreException: arraycopy: type mismatch: can not copy [Ljava.lang.String;[] into java.lang.String[]\n. Just for those who may also encounter this, my issue was the data storing in DB is not array but array of array.

huangapple
  • 本文由 发表于 2020年10月22日 13:15:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/64475717.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定