8

Tôi đang viết một ứng dụng mà tất cả các thuộc tính chuỗi phải được bản địa hóa, nghĩa là chúng phải lưu trữ một giá trị khác nhau cho mọi Ngôn ngữ có sẵn. Một giải pháp nhanh chóng sẽ được sử dụng một bản đồ, có thể dễ dàng ánh xạ trong Hibernate nhưng không phải là tốt đẹp trên các lập trình viên Java:Lập bản đồ chuỗi được bản địa hóa trong Hibernate - bất kỳ phương pháp hay nhất nào?

public class Product { 
    private Map<Locale, String> description; 
    private Map<Locale, String> note; 

Vì vậy, tôi thực hiện một đối tượng LocalString có thể chứa các chuỗi khác nhau cho miền địa phương khác nhau:

public class LocalString { 
    private Map<Locale, String> localStrings; 

Đối tượng miền trở nên

public class Product { 
    private LocalString description; 
    private LocalString note; 

làm thế nào để tốt nhất lập bản đồ các đối tượng này với chú thích Hibernate?

Tôi nghĩ rằng các bản đồ tốt nhất sẽ được thực hiện bằng LocalString như một thành phần:

@Embeddable 
public class LocalString { 
    private Map<Locale, String> localStrings; 

    @ElementCollection 
    public Map<Locale, String> getLocalStrings() { 
     return localStrings; 
    } 

...

@Entity 
public class Product { 
    private Long id; 
    private LocalString description; 
    private LocalString note; 

    @Embedded 
    public LocalString getDescription() { 
      return description; 
    } 

Tất cả là tốt cho đến nay: nhiệm vụ kiến ​​tạo hbm2ddl hai bảng, một Bảng "Sản phẩm" và bảng "Products_localStrings" chứa các cột khóa và giá trị. Mọi thứ đều bị hỏng khi tôi thêm bộ nạp cho thuộc tính thứ hai:

@Embedded 
    public LocalString getNote() { 
      return note; 
    } 

Thuộc tính thứ hai không hiển thị trong lược đồ. tôi đã cố gắng sử dụng thẻ @AttributesOverride để xác định tên gọi khác nhau cho hai cột, nhưng sơ đồ được tạo ra là không đúng:

@Embedded 
    @AttributeOverrides({ 
      @AttributeOverride(name="localStrings", [email protected](name="description")) 
    }) 
    public LocalString getDescription() { 
      return description; 
    } 
    @Embedded 
    @AttributeOverrides({ 
      @AttributeOverride(name="localStrings", [email protected](name="note")) 
    }) 
    public LocalString getNote() { 
      return note; 
    } 

Trong giản đồ được tạo ra, cột quan trọng đã biến mất và những ứng dụng khóa chính "mô tả" , không chính xác:

create table Product_localStrings (Product_id bigint not null, note varchar(255), description varchar(255), primary key (Product_id, description)); 

Mọi cách khắc phục lỗi này?

Tôi có nên tắt tốt hơn nếu không có các thành phần được nhúng, sử dụng LocalString làm thực thể không?

Bất kỳ thiết kế thay thế nào?

Cảm ơn bạn.

EDIT

Tôi đã thử với một ánh xạ xml và tôi quản lý để có được một sơ đồ thích hợp, nhưng chèn thất bại với một sự vi phạm khóa chính vì Hibernate tạo ra hai chèn thay vì chỉ một

<hibernate-mapping> 
    <class name="com.yr.babka37.demo.entity.Libro" table="LIBRO"> 
     <id name="id" type="java.lang.Long"> 
      <column name="ID" /> 
      <generator class="org.hibernate.id.enhanced.SequenceStyleGenerator"/> 
     </id> 
     <property name="titolo" type="java.lang.String"> 
      <column name="TITOLO" /> 
     </property> 
     <component name="descrizioni" class="com.yr.babka37.entity.LocalString"> 
     <map name="localStrings" table="libro_strings" lazy="true" access="field"> 
      <key> 
       <column name="ID" /> 
      </key> 
      <map-key type="java.lang.String"></map-key> 
      <element type="java.lang.String"> 
       <column name="descrizione" /> 
      </element> 
     </map> 
     </component> 
     <component name="giudizi" class="com.yr.babka37.entity.LocalString"> 
     <map name="localStrings" table="libro_strings" lazy="true" access="field"> 
      <key> 
       <column name="ID" /> 
      </key> 
      <map-key type="java.lang.String"></map-key> 
      <element type="java.lang.String"> 
       <column name="giudizio" /> 
      </element> 
     </map> 
     </component> 
    </class> 
</hibernate-mapping> 

Giản đồ là

create table LIBRO (ID bigint not null auto_increment, TITOLO varchar(255), primary key (ID)); 
create table libro_strings (ID bigint not null, descrizione varchar(255), idx varchar(255) not null, giudizio varchar(255), primary key (ID, idx)); 
alter table libro_strings add index FKF576CAC5BCDBA0A4 (ID), add constraint FKF576CAC5BCDBA0A4 foreign key (ID) references LIBRO (ID); 

Nhật ký:

DEBUG org.hibernate.SQL - insert into libro_strings (ID, idx, descrizione) values (?, ?, ?) 
DEBUG org.hibernate.SQL - insert into libro_strings (ID, idx, giudizio) values (?, ?, ?) 
WARN o.h.util.JDBCExceptionReporter - SQL Error: 1062, SQLState: 23000 
ERROR o.h.util.JDBCExceptionReporter - Duplicate entry '5-ita_ITA' for key 'PRIMARY' 

Làm cách nào để cho phép ngủ đông chỉ tạo một lần chèn như sau?

insert into libro_strings (ID, idx, descrizione, giudizio) values (?, ?, ?, ?) 

EDIT trên 2011.Apr.05

Tôi đã sử dụng giải pháp Bản đồ trong một thời gian (chú thích với @ElementCollection), cho đến khi tôi stumbled khi hai vấn đề:

Tôi biết có nhiều cách giải quyết, như sử dụng HQL thay vì tiêu chí và xác định FieldBridge của bạn để chăm sóc bản đồ trong Lucene, nhưng tôi không thích cách giải quyết: . Vì vậy, tôi là bây giờ sau tiếp cận này:

tôi định nghĩa một lớp "LocalString" chứa locale và giá trị (Locale thực sự là mã ISO3):

@MappedSuperclass 
public class LocalString { 
private long id; 
private String localeCode; 
private String value; 

Sau đó, tôi xác định, đối với mỗi tài sản tôi muốn để bản địa hoá, một lớp con của LocalString, mà là trống:

@Entity 
public class ProductName extends LocalString { 
    // Just a placeholder to name the table 
} 

Bây giờ tôi có thể sử dụng nó trong đối tượng sản phẩm của tôi:

public class Product { 
    private Map<String, ProductName> names; 

    @OneToMany(cascade=CascadeType.ALL, orphanRemoval=true) 
    @JoinColumn(name="Product_id") 
    @MapKey(name="localeCode") 
    protected Map<String, ProductName> getNames() { 
    return names; 
    } 

Với cách tiếp cận này, tôi phải viết một lớp trống cho mỗi thuộc tính mà tôi cần bản địa hóa, cần thiết để tạo một bảng duy nhất cho thuộc tính đó. Lợi ích là tôi có thể sử dụng Tiêu chí và Tìm kiếm mà không bị hạn chế.

+0

Các thử nghiệm khác cho thấy rằng Thuộc tínhOverrides thu gọn cả khóa và cột giá trị của bản đồ thành một cột. – xtian

+0

Tôi đã thử với ánh xạ xml và tôi đã quản lý để có được một lược đồ hợp lệ, nhưng sql được tạo bởi Hibernate lưu trữ mỗi thuộc tính trên một chèn khác, kết thúc bằng một vi phạm ràng buộc khóa chính. – xtian

+0

Thành thật mà nói, đây là nhiều hơn tôi đã đọc thời gian và tôi cho rằng có nhiều câu hỏi được đưa vào. Bạn nhận được sự hỗ trợ tốt hơn nhiều khi bạn có thể giảm bớt vấn đề cho một câu hỏi đơn giản, dễ mô tả. –

Trả lời

1

Ánh xạ xml của bạn không hoạt động vì bạn đã ánh xạ các loại giá trị vào cùng một bảng. Khi sử dụng phần tử hoặc phần tử hỗn hợp, dữ liệu được coi là các loại giá trị và thuộc về lớp được chứa. Nó yêu cầu bảng riêng của nó. Id chỉ là duy nhất trong bộ sưu tập.

Hoặc bản đồ nó như là thành phần:

<component name="descrizioni"> 
     <map name="localStrings" table="descrizioni_strings" ...> 
     <!-- ... --> 
     </map> 
    </component> 
    <component name="giudizi"> 
     <map name="localStrings" table="giudizi_strings" ... > 
     <!-- ... --> 
     </map> 
    </component> 

Hoặc như một thực thể độc lập:

<many-to-one name="descrizioni" class="LocalString"/> 
    <many-to-one name="giudizi" class="LocalString"/> 

Trong trường hợp thứ hai, LocalString là một thực thể. Nó cần một id và định nghĩa ánh xạ riêng của nó.

+0

Bạn nói đúng, tôi đã cố gắng sử dụng cùng một bảng cho cả hai bản đồ, điều này nghe có vẻ hay ngay từ đầu nhưng bây giờ tôi nhận ra điều này là sai. – xtian

+0

Trong giải pháp "thực thể độc lập", tất cả các chuỗi được bản địa hóa của ứng dụng của tôi chuyển đến cùng một bảng LocalString. Tôi không muốn điều này xảy ra, nhưng bây giờ tôi nhận ra rằng tôi không nói như vậy trong câu hỏi của mình. Tôi xin lỗi vì đã không làm rõ điều đó. – xtian

+0

Đối số "một bảng so với nhiều bảng" là một thứ khác có thể đáng để giải quyết. – xtian

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