2013-01-24 23 views
10

Chúng tôi đang sử dụng một loại chú thích JPA trông như thế này (mã groovy):Làm cách nào để di chuyển chuỗi PostgreSQL thành một loại văn bản?

@Entity 
@EqualsAndHashCode 
class TextNote extends Serializable { 
    @Id Long id 
    String text 
} 

Khi nó lần đầu tiên được viết Tôi rất mới để JPA và viết SQL đầu tiên, sau đó thực hiện các lớp chú thích phù hợp với SQL. Đọc lên trên PostgreSQL nó có vẻ như sau là bảng tôi muốn:

CREATE TABLE textnote (
    id bigint NOT NULL, 
    text text 
); 

này làm việc, và chúng tôi đã có bảng trông như thế này:

id |   text 
-----+------------------------ 
837 | really long text here 

Những gì tôi muốn làm bây giờ là đúng sự JPA Entity trông như thế này:

@Entity 
@EqualsAndHashCode 
class TextNote extends Serializable { 
    @Id Long id 
    @Lob String text 
} 

Bằng cách thêm chú thích @Lob nhà cung cấp JPA (trong trường hợp của tôi, hibernate) có thể tạo ra DDL một cách chính xác đối với tôi trong trường hợp chúng tôi muốn trao đổi cơ sở dữ liệu. Nó cũng tài liệu chính xác những gì tôi muốn trường văn bản được. Bây giờ khi một ghi chú được tạo ra tôi thấy một cái gì đó như thế này:

id |   text 
-----+------------------------ 
837 | 33427 

Điều gì là tốt cho ghi chú mới, khi tôi đọc nó trong mã bằng cách sử dụng String getText() nó trả về văn bản thực sự dài. Thành thật mà nói tôi không biết làm thế nào PostgreSQL thực hiện các loại text, cũng không phải tôi cần phải về mặt lý thuyết. Tuy nhiên cơ sở dữ liệu sản xuất của chúng tôi đã có nhiều ghi chú được lưu trữ bằng mã cũ mà không có chú thích @Lob. Chạy mã mới trên một cơ sở dữ liệu hiện có tạo ra các vấn đề như thế này:

org.springframework.dao.DataIntegrityViolationException: Bad value for type long : not a number this time; SQL [n/a]; nested exception is org.hibernate.exception.DataException: Bad value for type long : not a number this time 

Đối với ghi chú hiện có, là có một cách thức SQL để di chuyển các ghi chú cũ để sử dụng @Lobtext loại một cách chính xác? Cảm ơn trước.

Trả lời

12

Dựa trên Postgres large object docs có vẻ như bạn phải viết từng đoạn văn bản vào một tệp và nhập riêng từng tệp. Đó không phải là điều bạn nên làm trong SQL.

Tôi không biết gì về JPA, nhưng @Lob phải làm gì với DDL hoặc chuyển đổi cơ sở dữ liệu? Bạn đã hoàn toàn thay đổi loại cột; điều gì đã xảy ra với loại text của Postgres?


Kết thúc vòng lặp ở đây vì vậy đây không bị mất trong ý kiến:

Vấn đề thực sự là @Lob tạo ra một Postgres text cột, nhưng Hibernate treats it như một Postgres bản địa "đối tượng lớn" mà các cửa hàng dữ liệu ở nơi khác và chỉ để lại một oid trong bảng (sau đó được lưu trữ dưới dạng văn bản, theo loại cột). Đây không phải là những gì bạn muốn cho văn bản.

Giải pháp của OP là tát vào @Type(type="org.hibernate.type.StringClobType") để buộc Hibernate lưu trữ văn bản thông thường.

Postgres thường không lưu trữ văn bản dưới dạng số nguyên năm chữ số. :)

+0

Nếu không có chú thích đó, nhà cung cấp JPA sẽ tạo bảng có loại vARCHAR cột, đó không phải là điều tôi muốn. '@ Lob' tạo ra kiểu' văn bản' của PostgreSQL, chính xác là cái tôi muốn. Nếu tôi muốn chuyển đổi cơ sở dữ liệu, tôi muốn sử dụng nhà cung cấp JPA để tạo DDL cho tôi. '@ Lob' là cần thiết để làm điều đó. Có lý? – Joe

+0

bạn có chắc '@ Lob' đang tạo' văn bản' không? cả tài liệu và đầu ra đã đăng của bạn khiến tôi nghĩ rằng nó sẽ tạo ra 'oid' — đó là cách Postgres lưu trữ các đối tượng lớn. nếu nó thực sự là 'văn bản', bạn sẽ chỉ thấy _text_, không phải là một số bí ẩn. – Eevee

+0

Tôi tích cực, đây là bảng mà nó xuất ra với chú thích '@ Lob': [gist] (https://gist.github.com/4630173) – Joe

7

Tôi sử dụng JPA để chú thích các thực thể của mình và ngủ đông để duy trì chúng. Nhưng tôi không muốn thêm chú thích cụ thể ngủ đông vào thực thể của tôi. Vì vậy, tôi có một lọ dữ liệu chứa các thực thể + chú thích. Sau đó, trong triển khai của tôi, tôi chỉ định persistence.xml và thêm một 'CustomTypes.hbm.xml'.Được tự động quét hoặc được thêm vào thông qua thẻ tệp ánh xạ trong persistence.xml.

Ánh xạ này chứa các loại mà tôi muốn ghi đè từ basictyperegistry. Trong trường hợp này, loại materialized_clob được sử dụng. Mà tôi không muốn bởi vì khi tôi duyệt cơ sở dữ liệu của tôi với một công cụ truy vấn tôi muốn có thể xem trực tiếp nội dung thực tế. Vì vậy, tôi thêm:

<typedef name="materialized_clob" class="org.hibernate.type.TextType" /> 

Để buộc việc sử dụng các loại quy định cho tất cả CLOBs mà không cần phải thêm chú thích cụ thể trong gói dữ liệu của tôi.

Bạn có thể xem lại ánh xạ bằng cách ghi lại org.hibernate.type.BasicTypeRegistry trên mức DEBUG.

Tôi mất một thời gian để tìm hiểu điều này và tôi hy vọng điều này sẽ giúp mọi người đối mặt với cùng một vấn đề. Bởi vì điều này có lẽ cũng sẽ giải quyết vấn đề của bạn, tôi nghĩ rằng nó có thể là giá trị đăng nó ở đây.

0

Nếu sử dụng lò xo, bạn có thể tạo LocalSessionFactoryBean hậu duệ để chèn đè kiểu ghi đè kiểu Hibernate. Xem ví dụ:

public class CustomSessionFactoryBean extends LocalSessionFactoryBean { 

    @Override 
    protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) { 
     // To store @Lob annotated Strings in TEXT fields. 
     // By default for Postgres generated TEXT column, but stored OID of Postgres LOB object 
     sfb.registerTypeOverride(new TextType() { 
      @Override 
      public String getName() { 
       return StandardBasicTypes.MATERIALIZED_CLOB.getName(); 
      } 
     }); 
     sfb.registerTypeOverride(new NTextType() { 
      @Override 
      public String getName() { 
       return StandardBasicTypes.MATERIALIZED_NCLOB.getName(); 
      } 
     }); 

     super.buildSessionFactory(sfb); 
    } 
} 

Bạn không cần phải sử dụng Hibernate cụ chú thích @Type, chỉ cần chú thích sở hữu chuỗi với @Lob và sử dụng CustomSessionFactoryBean

1

Tôi chắc chắn cuối của nó, nhưng đối với bất cứ ai gặp vấn đề tương tự trong tương lai .

Tôi cũng gặp phải sự cố tương tự khi tôi có dữ liệu cũ trong các cột văn bản trực tiếp trong các cột không phải là OID. Và khi tôi đang cố gắng sử dụng dữ liệu đó với ứng dụng được nâng cấp, tôi cũng đã nhận được

Bad value for type long 

Để giải quyết vấn đề này, tôi đã tạo this script. Có thể nó có thể giúp ai đó trong tương lai.

Tôi nhận được trợ giúp lớn từ bài đăng này here

Các vấn đề liên quan