对单表策略使用鉴别符值时,第一个插入的实体的鉴别符值为null,但数据库中存在该值

问题描述

在将鉴别符值用于继承/单表策略时,第一个插入的实体的鉴别符值为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:

result null

我使用eclipse-link作为JPA实现和Java EE三层Web架构。 我知道这肯定与实体管理器的工作和持久性有关,但是我不知道细节。我也不知道该如何解决。欢迎任何建议!

解决方法

您没有在实体中设置'type'字段,并且JPA并未为您设置它-无论如何不在Java对象中。如果在持久化实体时未设置该属性,则只要该实体被缓存(本地或共享EMF级别的缓存),它将保持未设置状态。重新启动该应用程序之所以有效,是因为它清除了缓存,从而迫使从现有数据库中提取的所有现有实体都从数据库中加载,数据库的类型是根据区分符列值设置的。

您可以在创建类时设置类型,或通过在实例上调用em.refresh来强制从数据库中重新加载数据。但是,在这种情况下,即使将类型列映射为基本映射也似乎很奇怪-getType方法应该只返回该类的静态鉴别符值,并且您仍然不能更改类型字符串。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...