2010-06-30 35 views
17

Tôi đang sử dụng Hibernate 3.5.2-FINAL với chú thích để chỉ định ánh xạ liên tục của tôi. Tôi đang đấu tranh với mô hình hóa mối quan hệ giữa một Ứng dụng và một tập hợp các Nền tảng. Mỗi ứng dụng có sẵn cho một tập hợp các nền tảng.Thiết lập Enums liên tục trong bản đồ một chiều nhiều đối tượng

Từ tất cả việc đọc và tìm kiếm tôi đã thực hiện, tôi nghĩ rằng tôi cần phải có lớp enum nền tảng được tiếp tục tồn tại như một thực thể, và để có một bảng tham gia đại diện cho mối quan hệ nhiều-nhiều. Tôi muốn mối quan hệ là một chiều ở cấp độ đối tượng, có nghĩa là, tôi muốn có thể có được danh sách các nền tảng cho một ứng dụng cụ thể, nhưng tôi không cần phải tìm ra danh sách các ứng dụng cho một nền tảng nhất định.

Dưới đây là các lớp mô hình đơn giản của tôi:

@Entity 
@Table(name = "TBL_PLATFORM") 
public enum Platform { 
    Windows, 
    Mac, 
    Linux, 
    Other; 

    @Id 
    @GeneratedValue 
    @Column(name = "ID") 
    private Long id = null; 

    @Column(name = "NAME") 
    private String name; 

    private DevicePlatform() { 
     this.name = toString(); 
    } 

    // Setters and getters for id and name... 
} 

@Entity 
@Table(name = "TBL_APP") 
public class Application extends AbstractEntity implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Column(name = "NAME") 
    protected String _name; 

    @ManyToMany(cascade = javax.persistence.CascadeType.ALL) 
    @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE}) 
    @JoinTable(name = "TBL_APP_PLATFORM", 
       joinColumns = @JoinColumn(name = "APP_ID"), 
       inverseJoinColumns = @JoinColumn(name = "PLATFORM_ID")) 
    @ElementCollection(targetClass=Platform.class) 
    protected Set<Platform> _platforms; 

    // Setters and getters... 
} 

Khi tôi chạy công cụ hbm2ddl Hibernate, tôi thấy như sau (tôi đang sử dụng MySQL):

create table TBL_APP_PLATFORM (
    APP_ID bigint not null, 
    PLATFORM_ID bigint not null, 
    primary key (APP_ID, PLATFORM_ID) 
); 

Các phím nước ngoài thích hợp là cũng được tạo từ bảng này đến bảng ứng dụng và bảng nền tảng. Càng xa càng tốt.

Một vấn đề tôi đang chạy vào là khi tôi cố gắng để tồn tại một đối tượng áp dụng:

Application newApp = new Application(); 
newApp.setName("The Test Application"); 
Set<DevicePlatform> platforms = EnumSet.of(Platform.Windows, Platform.Linux); 
newApp.setPlatforms(platforms); 
applicationDao.addApplication(newApp); 

Những gì tôi muốn xảy ra là cho các hàng thích hợp trong bảng nền tảng để tạo ra, tức là tạo ra một hàng cho Windows và Linux, nếu chúng chưa tồn tại. Sau đó, một hàng cho ứng dụng mới sẽ được tạo và sau đó ánh xạ giữa ứng dụng mới và hai nền tảng trong bảng kết nối.

Một vấn đề tôi đang chạy vào là nhận được ngoại lệ thời gian chạy sau:

2010-06-30 13:18:09,382 6613126-0 ERROR FlushingEventListener Could not synchronize database state with session org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.example.model.Platform 

Bằng cách nào đó, các thiết lập nền tảng không được tồn khi tôi cố gắng kiên trì ứng dụng. Các chú thích xếp tầng được cho là phải quan tâm đến điều đó, nhưng tôi không biết có gì sai.

Vì vậy, câu hỏi của tôi là:

  1. Có cách nào tốt hơn để mô hình hóa những gì tôi muốn làm, ví dụ đang sử dụng Enum thích hợp?
  2. Nếu mô hình của tôi ổn, tôi làm cách nào để giữ nguyên tất cả các đối tượng?

Tôi đã vật lộn với điều này trong nhiều giờ và tôi đã cố gắng tạo lại tất cả mã ở trên nhưng có thể không hoàn chỉnh và/hoặc chính xác. Tôi hy vọng một người nào đó sẽ chỉ ra một cái gì đó hiển nhiên!

Trả lời

32

Bạn nên quyết định xem Platform là một thực thể hay không.

Nếu đó là một thực thể, nó không thể là enum, bởi vì danh sách các nền tảng có thể được lưu trữ trong cơ sở dữ liệu, không phải trong ứng dụng. Nó phải là một lớp thông thường với chú thích @Entity và bạn sẽ có mối quan hệ nhiều-nhiều.

Nếu nó không phải là một thực thể, thì bạn không cần TBL_PLATFORM bảng và bạn không có mối quan hệ nhiều-nhiều.Trong trường hợp này, bạn có thể đại diện cho một tập hợp của Platform s hoặc là một trường số nguyên với cờ bit, hoặc như một mối quan hệ một-nhiều đơn giản. JPA 2.0 làm cho các trường hợp sau đơn giản với @ElementCollection:

@ElementCollection(targetClass = Platform.class) 
@CollectionTable(name = "TBL_APP_PLATFORM", 
    joinColumns = @JoinColumn(name = "APP_ID")) 
@Column(name = "PLATFORM_ID") 
protected Set<Platform> _platforms; 

-

create table TBL_APP_PLATFORM ( 
    APP_ID bigint not null, 
    PLATFORM_ID bigint not null, -- the ordinal number of enum value 
    primary key (APP_ID, PLATFORM_ID) 
); 

enum Platform mà không chú thích.

+0

Tôi đã sử dụng một phiên bản cũ của Hibernate để tạo ra các giản đồ. Bằng cách làm theo http://stackoverflow.com/questions/2734971/hibernate3-maven-plugin-dependencies-for-newer-version-of-hibernate, tôi đặt phụ thuộc vào 3.5.3-FINAL và "org.hibernate.MappingException: Không thể xác định loại cho: java.util.Set "đã biến mất. Tôi đã làm theo phương pháp @ElementCollection mà bạn đã đề xuất, sử dụng enum không phải là thực thể đơn giản và bây giờ Đặt được ánh xạ tới một bảng tham gia. Và, bằng cách thiết lập @Enumerated trên tài sản, tôi có thể thiết lập cho dù các giá trị enum được lưu trữ trong cơ sở dữ liệu như số nguyên hoặc chuỗi. – gnuf

+0

@axtavt bạn có thể vui lòng giúp tôi với http://stackoverflow.com/questions/7687409/hibernate-criteria-query-for-collection-table/7693793#7693793 Tôi đã đính kèm tiền thưởng ở đó .. Rất cần trợ giúp .. –

+0

@ axtavt Bạn có thể thêm vào bài viết của mình cấu trúc của bảng nguyên tắc "TBL_APP" không? Thnx –

2

Sử dụng đơn giản dưới đây lập bản đồ trên thực thể của bạn. Giả sử rằng chúng ta có:

public enum TestEnum { A, B } 

Sau đó, trong lớp Entity của bạn:

@ElementCollection(targetClass = TestEnum.class) 
@CollectionTable(
     name = "yourJoinTable", 
     joinColumns = @JoinColumn(name = "YourEntityId") 
) 
@Column(name = "EnumId") 
private final Set<TestEnum> enumSet= new HashSet<TestEnum >(); 
Các vấn đề liên quan