簡體   English   中英

在沒有Hibernate Annotations的情況下糾正PostgreSQL文本類型的JPA注釋

[英]Correct JPA Annotation for PostgreSQL's text type without Hibernate Annotations

我正在開發一個應用程序:

  • Java 1.7
  • JPA(包含在javaee-api 7.0中)
  • Hibernate 4.3.8.Final
  • PostgreSQL-JDBC 9.4-1200-jdbc41
  • PostgreSQL 9.3.6

我想將PostgreSQL文本數據類型用於某些String屬性。 據我所知,在JPA中,這應該是正確的注釋,在PostgreSQL中使用文本:

@Entity
public class Product{
    ...
    @Lob
    private String description;
    ....
}

當我像這樣注釋我的實體時,我會遇到如下錯誤: http//www.shredzone.de/cilla/page/299/string-lobs-on-postgresql-with-hibernate-36.html

簡而言之:看起來hibernate和jdbc並不是clob / text-types的完美結合。

描述的解決方案正在運行:

@Entity
public class Product{
    ...
    @Lob
    @Type(type = "org.hibernate.type.TextType")
    private String description;
    ...
}

但這有一個明顯的缺點:源代碼在編譯時需要休眠,這應該是不必要的(這是首先使用JPA的一個原因)。

另一種方法是使用這樣的列注釋:

@Entity
public class Product{
    ...
    @Column(columnDefinition = "text")
    private String description;
    ...
}

哪個工作得很好,但是:現在我遇到了具有文本類型的數據庫(也稱為文本;))如果將來會使用另一個數據庫,注釋很容易被忽略。 因此,可能很難找到可能的錯誤,因為數據類型是在String中定義的,因此在運行時之前無法找到。

有沒有解決方案,這很容易,我只是看不到它? 我非常確定我不是唯一一個將JPA與Hibernate和PostgreSQL結合使用的人。 所以我有點困惑,我找不到更多像這樣的問題。

只是為了完成這個問題,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>

更新:

由於text類型不是SQL標准的一部分,因此我猜沒有正式的JPA方式。

但是, text類型與varchar非常相似,但沒有長度限制。 您可以使用@Columnlength屬性提示JPA實現:

@Column(length=10485760)
private String description;

更新: 10 MiB似乎是postgresql中varchar的最大長度。 根據文件 ,該text 幾乎是無限的:

在任何情況下,可存儲的最長字符串大約為1 GB。

如果你想使用普通的JPA,你可以重新映射Dialect上使用的CLOB類型,如下所示:

public class PGSQLMapDialect extends PostgreSQL9Dialect {


  @Override
  public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
    if (Types.CLOB == sqlTypeDescriptor.getSqlType()) {
      return LongVarcharTypeDescriptor.INSTANCE;
    }
    return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
  }


}

因此,它不會使用JDBC驅動程序中的CLOB映射,該驅動程序使用OID作為列,並通過大對象處理存儲/加載文本。 這只會導致通過VarcharTypeDescriptor類在Postgres JDBC驅動程序的createt文本列上調用setString和getString。

我只需要添加這個注釋:

@Column(columnDefinition="TEXT")

它本身不起作用。 我不得不在數據庫中重新創建表。

DROP TABLE yourtable或只是使用ALTER TABLE語句將列類型更改為text

我會使用簡單的private String description; 如果從代碼生成數據庫,則列類型只是一個問題,因為它將生成為varchar而不是text

以數據庫無關的方式進行編碼是很棒的,沒有任何JPA供應商特定的東西,但有些情況下這是不可能的。 如果現實是您必須支持多種數據庫類型及其所有細節,那么您必須在某處考慮這些細節。 一種選擇是使用columnDefinition來定義列類型。 另一種方法是保持代碼不變,只需更改數據庫中的列類型即可。 我更喜歡第二個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM