Java 在没有 Hibernate Annotations 的情况下为 PostgreSQL 的文本类型更正 JPA Annotation
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28588311/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Correct JPA Annotation for PostgreSQL's text type without Hibernate Annotations
提问by knoe
I'm developing an application using:
我正在使用以下方法开发应用程序:
- Java 1.7
- JPA (included in javaee-api 7.0)
- Hibernate 4.3.8.Final
- PostgreSQL-JDBC 9.4-1200-jdbc41
- PostgreSQL 9.3.6
- 爪哇 1.7
- JPA(包含在 javaee-api 7.0 中)
- 休眠 4.3.8.Final
- PostgreSQL-JDBC 9.4-1200-jdbc41
- PostgreSQL 9.3.6
And I would like to use the PostgreSQL text datatype for some String attributes. As far as I know, in JPA this should be the correct annotation, to use text in PostgreSQL:
我想对某些字符串属性使用 PostgreSQL 文本数据类型。据我所知,在 JPA 中,这应该是正确的注释,在 PostgreSQL 中使用文本:
@Entity
public class Product{
...
@Lob
private String description;
....
}
When I annotate my entity like this, I run into errors which look like this: http://www.shredzone.de/cilla/page/299/string-lobs-on-postgresql-with-hibernate-36.html
当我像这样注释我的实体时,我遇到了如下错误:http: //www.shredzone.de/cilla/page/299/string-lobs-on-postgresql-with-hibernate-36.html
In short: It seems that hibernate and jdbc go not hand in hand for clob/text-types.
简而言之:对于clob/text-types,hibernate和jdbc似乎并不一致。
The solution described is working:
所描述的解决方案正在工作:
@Entity
public class Product{
...
@Lob
@Type(type = "org.hibernate.type.TextType")
private String description;
...
}
But this has a significant downside: The source code needs hibernate at compile time, which should be unnecessary (That's one reason for using JPA in the first place).
但这有一个明显的缺点:源代码在编译时需要休眠,这应该是不必要的(这是首先使用 JPA 的一个原因)。
Another way is to use the column annotation like this:
另一种方法是像这样使用列注释:
@Entity
public class Product{
...
@Column(columnDefinition = "text")
private String description;
...
}
Which works nicely, BUT: Now I'm stuck with databases which have a text type (and is also called text ;) ) and if another database will be used in the future the annotations can be overlooked easily. Thus the possible error can be hard to find, because the datatype is defined in a String and therefore can not be found before runtime.
这很好用,但是:现在我坚持使用具有文本类型(也称为文本 ;) )的数据库,如果将来会使用另一个数据库,则注释很容易被忽略。因此很难找到可能的错误,因为数据类型是在字符串中定义的,因此在运行之前无法找到。
Is there a solution, which is so easy, I just don't see it? I'm very sure that I'm not the only one using JPA in combination with Hibernate and PostgreSQL. So I'm a little confused that I can't find more questions like this.
有没有解决方案,它是如此简单,我只是看不到它?我很确定我不是唯一一个将 JPA 与 Hibernate 和 PostgreSQL 结合使用的人。所以我有点困惑,我找不到更多这样的问题。
Just to complete the question, the persistence.xml looks like this:
为了完成这个问题,persistence.xml 看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="entityManager">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.app.model.Product</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url"
value="jdbc:postgresql://localhost:5432/awesomedb" />
<property name="javax.persistence.jdbc.user" value="usr" />
<property name="javax.persistence.jdbc.password" value="pwd" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="hibernate.jdbc.use_streams_for_binary" value="false" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
UPDATE:
更新:
This problem is more or less equivalent with this question, the picked answer is the second way to do it described in this question, which I don't like due to the hibernate runtime dependency: store strings of arbitrary length in Postgresql
This seems to be kind of related to: https://hibernate.atlassian.net/browse/JPA-48
这个问题或多或少与这个问题相同,选择的答案是这个问题中描述的第二种方法,由于休眠运行时依赖性,我不喜欢它: 在 Postgresql 中存储任意长度的字符串
这似乎与以下内容有关:https: //hibernate.atlassian.net/browse/JPA-48
回答by Predrag Maric
I would go with simple private String description;
. The column type is only a problem if you are generating the database from your code, because it will be generated as varchar
instead of text
.
我会选择 simple private String description;
。如果您从代码生成数据库,列类型只是一个问题,因为它将生成为varchar
而不是text
.
It is great to code in database agnostic way, and without any JPA vendor specific things, but there are cases where this just isn't possible. If the reality is that you will have to support multiple database types with all their specifics, then you have to account for those specifics somewhere. One option is to use columnDefinition
for defining column type. Another is to leave the code as it is, and just change the column type in the database. I prefer the second one.
以与数据库无关的方式进行编码非常棒,并且没有任何 JPA 供应商特定的东西,但在某些情况下这是不可能的。如果现实情况是您必须支持多种数据库类型及其所有细节,那么您必须在某处考虑这些细节。一种选择是columnDefinition
用于定义列类型。另一种是保留代码原样,只更改数据库中的列类型。我更喜欢第二个。
回答by holmis83
Since the text
type is not a part of the SQL standard there is no official JPA way I guess.
由于该text
类型不是 SQL 标准的一部分,所以我猜没有官方的 JPA 方式。
However, the text
type is quite similar to varchar
, but without the length limit. You can hint the JPA implementation with the length
property of @Column
:
但是,该text
类型与 非常相似varchar
,但没有长度限制。您可以使用以下length
属性提示 JPA 实现@Column
:
@Column(length=10485760)
private String description;
Update:10 MiB seems to be the maximum length for varchar
in postgresql. The text
is almostunlimited, according the documentation:
更新:10 MiB 似乎是varchar
postgresql 中的最大长度。该text
是几乎无限的,根据文档:
In any case, the longest possible character string that can be stored is about 1 GB.
在任何情况下,可以存储的最长字符串大约是 1 GB。
回答by Torsten Krah
If you want to use plain JPA you could just remap the used CLOB type on the Dialect like this:
如果你想使用普通的 JPA,你可以像这样在方言上重新映射使用过的 CLOB 类型:
public class PGSQLMapDialect extends PostgreSQL9Dialect {
@Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
if (Types.CLOB == sqlTypeDescriptor.getSqlType()) {
return LongVarcharTypeDescriptor.INSTANCE;
}
return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
}
}
So it won't use the CLOB mapping from the JDBC driver which uses a OID for the column and stores/loads the text via large object handling. This would just result in setString and getString calls on the createt text column on the Postgres JDBC Driver via the VarcharTypeDescriptor class.
因此,它不会使用来自 JDBC 驱动程序的 CLOB 映射,该驱动程序为列使用 OID 并通过大对象处理存储/加载文本。这只会导致通过 VarcharTypeDescriptor 类对 Postgres JDBC 驱动程序上的 createt 文本列进行 setString 和 getString 调用。
回答by Eliska P.
I just had to add this annotation:
我只需要添加这个注释:
@Column(columnDefinition="TEXT")
It did not work on its own. I had to recreate the table in the database.
它没有单独工作。我不得不在数据库中重新创建表。
DROP TABLE yourtable
or just alter column type to text
with ALTER TABLE
statement
DROP TABLE yourtable
或者只是将列类型更改为text
withALTER TABLE
语句