对ORM / JPA使用单表策略时,如何使用从JPQL的父实体继承的属性列

问题描述

我有3个班级:User,Admin,normalUser

Admin和normalUser扩展了用户类,当映射到derby db表时,我使用单表策略进行继承,并且发现如果我在normalUser类中使用继承的属性编写命名查询,则会出现错误。可以从下面的代码中引用更多信息:

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

package entity;


import java.io.Serializable;
import java.util.LinkedHashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.discriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OnetoMany;



@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="user",cascade = {CascadeType.PERSIST,CascadeType.MERGE}) //delete user will delete all customer
    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;
//  }
}

如果我使用普通用户的继承属性编写命名查询

package entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OnetoMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

@Entity
@Table(name="CUSTOMER")
@NamedQueries({
    @NamedQuery(name = "Customer.findAll",query = "SELECT c FROM Customer c order by c.customerID desc"),@NamedQuery(name = "Customer.findByUser",query = "SELECT c FROM Customer c WHERE c.normalUser.account = :account")
})
public class Customer implements Serializable {
    
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private int customerID;
    private Industry customerIndustryType;
    private String customerName;
    private Address customerAddress;
    private String customerNationality;
    private Date customerAddedDate;
    private Double customerdiscountRate;
    private String customerScale;
    private List<Contact> customerContacts;
    private normalUser normalUser;
    //getter and setter omited .....
}

运行它时将引发错误,并且显然与访问父属性的此查询有关:

screenshot of error information

实际上,我也尝试使用标准API,但它也失败了:

//          customers = entityManager.createNamedQuery("Customers.findByAccount",Customer.class).setParameter("account",role).getResultList();
//          CriteriaBuilder builder = entityManager.getCriteriaBuilder();
//          CriteriaQuery<Customer> criteriaQuery = builder.createquery(Customer.class);
//          Root<Customer> c = criteriaQuery.from(Customer.class);
//          criteriaQuery.select(c).where(builder.equal(c.get("normalUser").get("account"),role)); //(p.get("price"),budget));//danger4
//          Query query = entityManager.createquery(criteriaQuery);     
//          //List<Property> properties = query.getResultList();
//          customers =  query.getResultList();

那么如何使用父对象的属性?它不应该是这样。如果我扩展类,我将拥有所有继承的属性,不是吗?

-------------------------------------------------更新- ----------------------------

继承的属性可以在JPQL中使用。只是我们必须始终记得在对它进行注释时检查getter名称,这是JPQL中解决的问题。 希望将来的访客记得注意细节。 大声笑,最大的错误来自最简单的错误。 好消息是由于这个错误,我必须通过user.getCustomers()访问客户,因为它是双向的。结果,我学到了很多保持双向关系的方法

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

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