问题描述
我正在尝试在我的 Book 实体和我通过服务检索的语言列表之间建立关系。 在我的数据库中,每本书都有一个:ID、TITLE、CATEGORY_ID (FK)、LANG_ID
Book.java:
@Entity
@Table(schema = Constants.SHEMA,name = "Book")
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private long id;
@Column(name = "TITLE")
private String title;
@ManyToOne(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
@JoinColumn(name = "CATEGORY_ID")
private Category category;
private Language language; // -> The Column associated in the database is Long LANG_ID
}
类别.java:
@Entity
@Table(schema = Constants.SHEMA,name = "Category")
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private Long id;
@Column(name = "NAME")
private String name;
}
语言.java:
public class Language implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
}
我理解 Book 和 Category 之间的关系,因为它们都是我数据库中的表。但是,Language 是我从服务中获得的东西,并没有保留在我的数据库中。 我得到的语言只是语言的 ID 和名称。
我的问题是:为了将语言 ID 链接到我的 LANG_ID(我的 Book 表中语言的 ID),我应该为 Language 编写什么注释(ManyToOne、Entity...)?我也应该把它放在我的 persistence.xml 中吗?我尝试了几个,但似乎效果不佳。
非常感谢
解决方法
首先,您是否考虑在您的数据库中存储语言?我的意思是语言大体相同,不会经常更改,您也可以将它们存储在属性文件中并在运行时读取它们以备后用。
无论如何,我认为你应该:
- 首先从外部系统语言获取
- 存储在变量/内存缓存中(例如 Map
,您可以在其中存储 id 和 name) - 从数据库中读取数据
- 对于你所做的每一行
- 读取书籍语言 ID,读取缓存,获取您需要的数据
- 对于你所做的每一行
如果您无法更改模型,只需将 dto 与您的实体和语言一起使用即可
,我认为将持久化数据与非持久化数据混合在一起不是一个好习惯,因为这会导致其他意外问题。无论如何,你可以尝试这样的事情:
@Entity
@Table(schema = Constants.SHEMA,name = "Book")
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID")
private long id;
@Column(name = "TITLE")
private String title;
@ManyToOne(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
@JoinColumn(name = "CATEGORY_ID")
private Category category;
@Column(name = "LANG_ID")
private Integer langId;
@Transient
private Language language;
@PostLoad
public void loadLanguage() {
// get the language data here
}
}
language
字段没有数据库表,因此您不能使用任何映射注释。来自 Java EE 文档:
public @interface Transient
Specifies that the property or field is not persistent. It is used to annotate a property or field of an entity class,mapped superclass,or embeddable class.
Example:
@Entity
public class Employee {
@Id int id;
@Transient User currentUser;
...
}
@PostLoad
注释声明了一个在实体加载后要调用的方法:
public @interface PostLoad
Specifies a callback method for the corresponding lifecycle event. This annotation may be applied to methods of an entity class,a mapped superclass,or a callback listener class.