如何在 Java 中自动加载具有 @ManyToMany 关系的实体
How to automatically load Entities with @ManyToMany relations in Java
我正在尝试学习如何创建一个 Java 企业应用程序(目前正在使用 EclipseLink),其中我有一个 User
实体与一个 @ManyToMany
关系Card
实体,但是当用户从数据库中加载时,卡片属性不会像我预期的那样自动填充。
这是我的用户实体:
@Entity
@Table(name = "USR")
public class User extends Person implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "CPF", unique = true, nullable = false)
private String cpf;
@Column(name = "USERNAME", length = 20, nullable = false, unique = true)
private String username;
@Column(name = "BDAY")
@Temporal(TemporalType.DATE)
private Date bDay;
@Column(name = "EMAIL", length = 100, nullable = false, unique = true)
private String email;
@ManyToMany
private List<Card> cards;
public User() {
super();
}
}
这是我的卡片实体:
@Entity
public class Card implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String number;
@Column(name = "EXP_DATE")
@Temporal(TemporalType.DATE)
private Date expDate;
@Column(name = "VALIDATOR")
private int validator;
@Transient
private String endsWith;
public Card() {
}
}
因此,当我的 servlet
被实例化时,我会像这样 userBean.setUser(userFactoryEJB.find(2));
从数据库中加载一个用户并且它工作正常,我能够访问用户电子邮件、生日、用户名等。但是,当我尝试获取用户卡时,我收到以下消息 {IndirectList: not instantiated}
。在有人问之前,我确实尝试在 User 构造函数上初始化列表,但出现了相同的消息。
我期望的是,用户从数据库中加载时,他们的所有卡片都已加载到 card 属性中。
集合值关系的默认获取类型是惰性的。提交事务时,所有加载的实体都将分离,您无法访问延迟加载实体。
我认为您在另一笔交易中检索了用户。
请检查您的 TransactionAttribute 注释。
一些可能的解决方案是:
1)您是在 CDI bean 中还是在另一个会话 bean 中使用 userFactoryEJB?您必须从另一个会话 bean 调用 userFactoryEJB 或在您的 CDI bean 上使用@Transactional。
2) 将获取类型更改为 eager。
@ManyToMany(fetch = FetchType.EAGER)
private List<Card> cards;
3)定义另一个find方法并在返回用户之前调用getcrads()方法
我正在尝试学习如何创建一个 Java 企业应用程序(目前正在使用 EclipseLink),其中我有一个 User
实体与一个 @ManyToMany
关系Card
实体,但是当用户从数据库中加载时,卡片属性不会像我预期的那样自动填充。
这是我的用户实体:
@Entity
@Table(name = "USR")
public class User extends Person implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "CPF", unique = true, nullable = false)
private String cpf;
@Column(name = "USERNAME", length = 20, nullable = false, unique = true)
private String username;
@Column(name = "BDAY")
@Temporal(TemporalType.DATE)
private Date bDay;
@Column(name = "EMAIL", length = 100, nullable = false, unique = true)
private String email;
@ManyToMany
private List<Card> cards;
public User() {
super();
}
}
这是我的卡片实体:
@Entity
public class Card implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String number;
@Column(name = "EXP_DATE")
@Temporal(TemporalType.DATE)
private Date expDate;
@Column(name = "VALIDATOR")
private int validator;
@Transient
private String endsWith;
public Card() {
}
}
因此,当我的 servlet
被实例化时,我会像这样 userBean.setUser(userFactoryEJB.find(2));
从数据库中加载一个用户并且它工作正常,我能够访问用户电子邮件、生日、用户名等。但是,当我尝试获取用户卡时,我收到以下消息 {IndirectList: not instantiated}
。在有人问之前,我确实尝试在 User 构造函数上初始化列表,但出现了相同的消息。
我期望的是,用户从数据库中加载时,他们的所有卡片都已加载到 card 属性中。
集合值关系的默认获取类型是惰性的。提交事务时,所有加载的实体都将分离,您无法访问延迟加载实体。
我认为您在另一笔交易中检索了用户。
请检查您的 TransactionAttribute 注释。
一些可能的解决方案是:
1)您是在 CDI bean 中还是在另一个会话 bean 中使用 userFactoryEJB?您必须从另一个会话 bean 调用 userFactoryEJB 或在您的 CDI bean 上使用@Transactional。
2) 将获取类型更改为 eager。
@ManyToMany(fetch = FetchType.EAGER)
private List<Card> cards;
3)定义另一个find方法并在返回用户之前调用getcrads()方法