問題描述
我正在使用帶有注釋的 Hibernate 3.5.2-FINAL 來指定我的持久性映射.我正在努力為應用程序和一組平臺之間的關系建模.每個應用程序都可用于一組平臺.
I'm using Hibernate 3.5.2-FINAL with annotations to specify my persistence mappings. I'm struggling with modelling a relationship between an Application and a set of Platforms. Each application is available for a set of platforms.
從我所做的所有閱讀和搜索中,我認為我需要將平臺枚舉類作為實體持久化,并有一個連接表來表示多對多關系.我希望關系在對象級別是單向的,也就是說,我希望能夠獲取給定應用程序的平臺列表,但我不需要找出給定平臺的應用程序列表.
From all the reading and searching I've done, I think I need to have the platform enum class be persisted as an Entity, and to have a join table to represent the many-to-many relationship. I want the relationship to be unidirectional at the object level, that is, I want to be able to get the list of platforms for a given application, but I don't need to find out the list of applications for a given platform.
這是我的簡化模型類:
@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...
}
當我運行 Hibernate hbm2ddl 工具時,我看到以下內容(我使用的是 MySQL):
When I run the Hibernate hbm2ddl tool, I see the following (I'm using MySQL):
create table TBL_APP_PLATFORM (
APP_ID bigint not null,
PLATFORM_ID bigint not null,
primary key (APP_ID, PLATFORM_ID)
);
相應的外鍵也從該表創建到應用程序表和平臺表.到目前為止一切順利.
The appropriate foreign keys are also created from this table to the application table and platform table. So far so good.
我遇到的一個問題是當我嘗試持久化應用程序對象時:
One problem I'm running into is when I try to persist an application object:
Application newApp = new Application();
newApp.setName("The Test Application");
Set<DevicePlatform> platforms = EnumSet.of(Platform.Windows, Platform.Linux);
newApp.setPlatforms(platforms);
applicationDao.addApplication(newApp);
我希望在 Platform 表中創建適當的行,即為 Windows 和 Linux 創建一行,如果它們不存在的話.然后,應該為新應用程序創建一行,然后在連接表中創建新應用程序與兩個平臺之間的映射.
What I would like to happen is for the appropriate rows in the Platform table to created, i.e. create a row for Windows and Linux, if they don't already exist. Then, a row for the new application should be created, and then the mapping between the new application and the two platforms in the join table.
我遇到的一個問題是出現以下運行時異常:
One issue I'm running into is getting the following runtime exception:
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
不知何故,當我嘗試持久化應用程序時,平臺集沒有被持久化.級聯注釋應該可以解決這個問題,但我不知道出了什么問題.
Somehow, the platform set is not being persisted when I try to persist the application. The cascade annotations are supposed to take care of that, but I don't know what's wrong.
所以我的問題是:
- 有沒有更好的方法來模擬我想做的事情,例如使用 Enum 合適嗎?
- 如果我的模型沒問題,如何正確持久化所有對象?
我已經為此苦苦掙扎了好幾個小時,并嘗試重新創建上面的所有代碼,但它可能不完整和/或不準確.我希望有人會指出一些明顯的事情!
I've been struggling with this for hours, and I've tried to recreate all of the code above, but it might not be complete and/or accurate. I'm hoping someone will point out something obvious!
推薦答案
你應該決定你的Platform
是否是一個entity.
You should decide whether your Platform
is an entity or not.
如果是實體,則不能是enum
,因為可能的平臺列表存儲在數據庫中,而不是應用程序中.它應該是帶有 @Entity
注釋的常規類,并且您將具有正常的多對多關系.
If it's an entity, it can't be an enum
, because list of possible platforms is stored in the database, not in the application. It should be a regular class with @Entity
annotation and you will have a normal many-to-many relation.
如果不是實體,則不需要TBL_PLATFORM
表,也沒有多對多關系.在這種情況下,您可以將一組 Platform
表示為帶有位標志的整數字段,或者表示為簡單的一對多關系.JPA 2.0 使用 @ElementCollection
使后一種情況變得簡單:
If it isn't an entity, then you don't need TBL_PLATFORM
table, and you don't have a many-to-many relation. In this case you can represent a set of Platform
s either as an integer field with bit flags, or as a simple one-to-many relation. JPA 2.0 makes the latter case simple with @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
沒有注釋.
這篇關于在多對多單向映射中持久化枚舉集的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!