Я пытаюсь использовать JPA в первый раз в проекте. Большинство моих сущностей работают нормально, но у меня возникают проблемы с тем, что является частью стратегии наследования наследования. Сущности также сериализуются Jackson, поэтому у них также есть аннотации Json.JPA Сущность игнорируется
Родительский класс "Пользователь": (Edit: добавлено поле "Тип")
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include= JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonTypeName("user")
@JsonSubTypes({
@JsonSubTypes.Type(name="customer", value=Customer.class),
@JsonSubTypes.Type(name="employee", value=Employee.class)})
@Entity(name = "User")
@Table(name="user")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name="type",discriminatorType = DiscriminatorType.INTEGER)
@NamedQuery(name="User.all",query = "select u from User u")
public abstract class User {
@Id
private String username;
@Column(name = "type",nullable = false)
private int type;
public User(){
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public abstract Set<Order> getOrders();
}
Ребенок "Сотрудник"
@JsonTypeName("employee")
@Entity(name="Employee")
@Table(name="employee")
@PrimaryKeyJoinColumn(name = "username",referencedColumnName = "username")
@DiscriminatorValue("1")
@NamedQuery(name = "Employee.all",query = "select e from Employee e")
public class Employee extends User implements Serializable{
private String username;
private String firstName;
private String lastName;
private String email;
@Convert(converter = LocalDatePersistenceConverter.class)
private LocalDate dateStarted;
@Convert(converter = LocalDatePersistenceConverter.class)
private LocalDate dateEnded;
@OneToMany(mappedBy = "employee",targetEntity = Order.class,fetch = FetchType.EAGER,cascade = CascadeType.PERSIST)
@JsonIgnore
private Set<Order> orders = new HashSet<>();
public Employee() {
}
@Override
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
public void addOrder(Order order){
orders.add(order);
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
public String getDateStarted() {
if(dateStarted != null)
return dateStarted.toString();
else return null;
}
public void setDateStarted(LocalDate dateStarted) {
this.dateStarted = dateStarted;
}
public String getDateEnded() {
if(dateEnded != null)
return dateEnded.toString();
else return null;
}
public void setDateEnded(LocalDate dateEnded) {
this.dateEnded = dateEnded;
}
@Override
public String toString(){
return getUsername();
}
}
И ребенок "Клиент": (Edit : удалены @Id поле)
@JsonTypeName("customer")
@Entity(name="Customer")
@Table(name="customer")
@PrimaryKeyJoinColumn(name = "username",referencedColumnName = "username")
@DiscriminatorValue("2")
@NamedQueries({
@NamedQuery(name="Customer.all",query = "select c from Customer c")
})
public class Customer extends User implements Serializable{
public enum VIP_TYPE {NORMAL,SILVER,GOLD,DIAMOND}
@Transient
private static final int SILVER_THRESHOLD = 1000;
@Transient
private static final int GOLD_THRESHOLD = 2000;
@Transient
private static final int DIAMOND_THRESHOLD = 3000;
private String firstName;
private String lastName;
private String email;
private String address;
private String postcode;
private String mobileNumber;
private String homeNumber;
@Convert(converter = VipTypeConverter.class)
private VIP_TYPE vipGroup;
private String discount;
@OneToMany(mappedBy = "customer",targetEntity = Order.class,fetch=FetchType.EAGER,cascade = CascadeType.ALL)
@JsonIgnore
private Set<Order> orders = new HashSet<>();
public Customer() {
}
@Override
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
}
public void addOrder(final Order order){
orders.add(order);
updateVipGroup();
}
private void updateVipGroup() {
int sum = orders.stream().map(Order::getPayment).distinct().mapToInt(p->p.getAmmount()).sum();
if(sum > DIAMOND_THRESHOLD){
vipGroup = VIP_TYPE.DIAMOND;
return;
}
if(sum > GOLD_THRESHOLD){
vipGroup = VIP_TYPE.GOLD;
return;
}
if(sum > SILVER_THRESHOLD){
vipGroup = VIP_TYPE.SILVER;
return;
}
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setEmail(String email) {
this.email = email;
}
public void setAddress(String address) {
this.address = address;
}
public void setDiscount(String discount) {
this.discount = discount;
}
public void setVipGroup(VIP_TYPE vipGroup) {
this.vipGroup = vipGroup;
}
public void setHomeNumber(String homeNumber) {
this.homeNumber = homeNumber;
}
public void setMobileNumber(String mobileNumber) {
this.mobileNumber = mobileNumber;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}
public String getDiscount() {
return discount;
}
public VIP_TYPE getVipGroup() {
return vipGroup;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
public String getAddress() {
return address;
}
public String getPostcode() {
return postcode;
}
public String getMobileNumber() {
return mobileNumber;
}
public String getHomeNumber() {
return homeNumber;
}
}
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="local" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/cod</jta-data-source>
<class>com.technicalpioneers.cod.user.Customer</class>
<class>com.technicalpioneers.cod.user.Employee</class>
<class>com.technicalpioneers.cod.user.User</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
</persistence-unit>
</persistence>
Все делать с «работником» работает файл, я могу использовать именованный запрос Employee.all
найти всех сотрудников в базе данных.
Однако, если я пытаюсь найти всех клиентов, я получаю ошибки. Если я пытаюсь запустить именованный запрос Customer.all
я получаю:
java.lang.IllegalArgumentException: NamedQuery of name: Customer.all not found.
Если я пытаюсь использовать находку EntityManager (в) метод, чтобы найти конкретный клиент, я получаю:
javax.servlet.ServletException: Exception [EclipseLink-43] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Missing class for indicator field value [2] of type [class java.lang.Integer].
Descriptor: RelationalDescriptor(com.technicalpioneers.cod.user.User --> [DatabaseTable(user)])
Я не понимаю, почему организация-заказчик не находится в JPA. Я проверил таблицу пользователя, и столбец «type» там с правильными номерами, и @DescriminatorValue установлен правильно. Это похоже на то, что аннотации игнорируются?
Проделали много чистых перестроек и перераспределителей. Любая помощь будет очень высоко ценится!
Я вижу, что вы определили имя пользователя @Id private String; в компоненте Customer, но не в Employee. Я думаю, вы должны держать его в соответствии. (если я правильно помню, он должен быть определен только в родительском) –
любые изменения, которые вы поместили в класс клиента в неправильном пакете? Или в тестовой ветке кода? Нет ошибок jpa в журналах при запуске? – Zielu
Спасибо за быстрые ответы! Поле @Id в клиенте - это то, что я добавил в качестве эксперимента после начала проблемы, я удалил его снова и не изменил. – Rag