服务中实体和对象之间的关系

Relation between Entity and Object from service

我试图在我的 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
 
}

Category.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;
}

Language.java:

public class Language implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    private Long id;
 
    private String name;
}
 

我了解图书和类别之间的关系,因为它们在我的数据库中都是 table。但是,语言是我从服务中获得的东西,并没有保存在我的数据库中。 我得到的语言只是语言的 ID 和名称。

我的问题是:为了link我LANG_ID的语言ID(我的Book中的语言IDtable),什么注解(ManyToOne,Entity, ...) 我应该为语言写作吗?我也应该把它放在我的 persistence.xml 中吗?我尝试了几次,但似乎效果不佳。

非常感谢

首先,您是否考虑过将语言存储在您的数据库中?我的意思是语言大多相同,不会经常更改,您也可以存储在属性文件中并在运行时读取它们以供以后使用。

无论如何,我认为你应该:

  • 首先从外部系统语言获取
  • 存储在变量/内存缓存中(比如 Map 可以存储 id 和名称)
  • 从数据库读取数据
    • 你做的每一行
      • 阅读图书语言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字段没有数据库table,所以不能使用任何映射注解。来自 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.