问题描述
在将鉴别符值用于继承/单表策略时,第一个插入的实体的鉴别符值为null,但该值存在于数据库中。 我必须重新启动服务器,以便查询结果包含鉴别符值:
package entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.discriminatorColumn;
import javax.persistence.discriminatorType;
import javax.persistence.discriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.MappedSuperclass;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@discriminatorColumn(name="user_type",discriminatorType = discriminatorType.STRING)
@discriminatorValue("Null")
@Table(name="ALLUSER")
@NamedQueries({
@NamedQuery(name = "User.findAll",query = "SELECT u FROM User u"),@NamedQuery(name = "User.findByAccount",query = "SELECT u FROM User u WHERE u.account = :account")
})
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String account;
private String password;
private String userType;
public User() {
super();
}
public User(String account,String password) {
super();
this.account = account;
this.password = password;
}
@Id
@Column(name = "account")
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
@Column(name = "password")
public String getpassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Column(name = "user_type",insertable = false,updatable = false,nullable = false)
public String getUserType() {
return userType;
}
public void setUserType(String userType) {
this.userType = userType;
}
@Override
public String toString() {
return account;
}
}
@Entity
@discriminatorValue("normal")
@NamedQueries({
@NamedQuery(name = "normalUser.findAll",query = "SELECT u FROM normalUser u")
})
public class normalUser extends User implements Serializable{
/**
*
*/
//private String account;
private static final long serialVersionUID = 1L;
private LinkedHashSet<Customer> customers;
public normalUser() {
super();
}
@OnetoMany(fetch=FetchType.EAGER,mappedBy="normalUser",cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE}) //eager can be optimized when deleting a normal user
public LinkedHashSet<Customer> getCustomers() {
return customers;
}
public void setCustomers(LinkedHashSet<Customer> customers) {
this.customers = customers;
}
// @Column(name = "account")
// //have to override in order to get account to use
// public String getAccount() {
// return account;
// }
//
// public void setAccount(String account) {
// this.account = account;
// }
}
如果我仅添加一个新的普通用户(子实体),则查询该用户,其用户类型将为null:
我使用eclipse-link作为JPA实现和Java EE三层Web架构。 我知道这肯定与实体管理器的工作和持久性有关,但是我不知道细节。我也不知道该如何解决。欢迎任何建议!
解决方法
您没有在实体中设置'type'字段,并且JPA并未为您设置它-无论如何不在Java对象中。如果在持久化实体时未设置该属性,则只要该实体被缓存(本地或共享EMF级别的缓存),它将保持未设置状态。重新启动该应用程序之所以有效,是因为它清除了缓存,从而迫使从现有数据库中提取的所有现有实体都从数据库中加载,数据库的类型是根据区分符列值设置的。
您可以在创建类时设置类型,或通过在实例上调用em.refresh来强制从数据库中重新加载数据。但是,在这种情况下,即使将类型列映射为基本映射也似乎很奇怪-getType方法应该只返回该类的静态鉴别符值,并且您仍然不能更改类型字符串。