gnu*_*nuf 20 java persistence annotations hibernate jpa
我正在使用带有注释的Hibernate 3.5.2-FINAL来指定我的持久性映射.我正在努力建立应用程序和一组平台之间的关系.每个应用程序都可用于一组平台.
从我所做的所有阅读和搜索中,我认为我需要将平台枚举类保持为实体,并使用连接表来表示多对多关系.我希望关系在对象级别是单向的,也就是说,我希望能够获得给定应用程序的平台列表,但我不需要找出给定平台的应用程序列表.
这是我的简化模型类:
@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...
}
Run Code Online (Sandbox Code Playgroud)
当我运行Hibernate hbm2ddl工具时,我看到以下内容(我正在使用MySQL):
create table TBL_APP_PLATFORM (
APP_ID bigint not null,
PLATFORM_ID bigint not null,
primary key (APP_ID, PLATFORM_ID)
);
Run Code Online (Sandbox Code Playgroud)
还将从此表创建适当的外键到应用程序表和平台表.到现在为止还挺好.
我遇到的一个问题是当我尝试持久化应用程序对象时:
Application newApp = new Application();
newApp.setName("The Test Application");
Set<DevicePlatform> platforms = EnumSet.of(Platform.Windows, Platform.Linux);
newApp.setPlatforms(platforms);
applicationDao.addApplication(newApp);
Run Code Online (Sandbox Code Playgroud)
我想要发生的是创建Platform表中的相应行,即为Windows和Linux创建一行(如果它们尚不存在).然后,应创建新应用程序的行,然后创建新应用程序与连接表中的两个平台之间的映射.
我遇到的一个问题是获得以下运行时异常:
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
Run Code Online (Sandbox Code Playgroud)
不知何故,当我尝试持久化应用程序时,平台集不会被持久化.级联注释应该照顾它,但我不知道什么是错的.
所以我的问题是:
我一直在努力解决这个问题几个小时,我试图重新创建上面的所有代码,但它可能不完整和/或准确.我希望有人会指出一些明显的东西!
axt*_*avt 40
您应该决定您是否Platform
是实体.
如果它是一个实体,它不能是一个实体,enum
因为可能的平台列表存储在数据库中,而不是存储在应用程序中.它应该是带有@Entity
注释的常规类,并且您将具有正常的多对多关系.
如果它不是实体,那么您不需要TBL_PLATFORM
表,并且您没有多对多关系.在这种情况下,您可以将一组Platform
s 表示为带有位标志的整数字段,或者表示为简单的一对多关系.JPA 2.0使后一种情况变得简单@ElementCollection
:
@ElementCollection(targetClass = Platform.class)
@CollectionTable(name = "TBL_APP_PLATFORM",
joinColumns = @JoinColumn(name = "APP_ID"))
@Column(name = "PLATFORM_ID")
protected Set<Platform> _platforms;
Run Code Online (Sandbox Code Playgroud)
-
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)
);
Run Code Online (Sandbox Code Playgroud)
并enum Platform
没有标注.
小智 5
在您的实体上简单使用下面的映射。假设我们有:
public enum TestEnum { A, B }
Run Code Online (Sandbox Code Playgroud)
然后在您的实体类中:
@ElementCollection(targetClass = TestEnum.class)
@CollectionTable(
name = "yourJoinTable",
joinColumns = @JoinColumn(name = "YourEntityId")
)
@Column(name = "EnumId")
private final Set<TestEnum> enumSet= new HashSet<>();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
20464 次 |
最近记录: |