JPA causes trouble for itself - java

I'm using JPA/EclipseLink, it throws this exception
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:
Unknown column 'NAME' in 'field list'
Below is the generated query:
Call: SELECT id, DTYPE, fullname, NAME, code FROM PERSON WHERE
((accountId = ?) AND (DTYPE = ?)) bind => [1, Employee]
in which
#Entity
#Table(name = "PERSON")
public class Person
implements Serializable {
....
#Column(name = "fullname", nullable = false)
public String getFullName() {
return this.fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
....
}
#Entity
#Table(name="EMPLOYEE")
#PrimaryKeyJoinColumn(name="personId")
public class Employee
extends Person
implements Serializable {
....
#Column(name="code")
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
I don't have the NAME column on neither PERSON table nor EMPLOYEE table, why does it casually add that column to the query and cause the problem for itself (and for me)?
--- EDITED -----
I don't have any name property or member or something similar to that word in either PERSON nor EMPLOYEE entity.

NAME looks like it is defaulting (since you seem to set the field names as lower case), so check for a getName/setName methods in the Person class. Are you using an orm.xml file?
If you still cannot find the problem, turn EclipseLink logging to Finest:
and check the log during predeployment/deployment stages. The EclipseLink processing for the Person and Employee classes should show why it is determining there should be a NAME field.

Related

Getting Exception while getting data from 2 db tables with TABLE_PER_CLASS Inheritance

I am trying to get data from 2 db table which have same columns in both tables
For that am trying following but getting Exception as
- (conn:106433) Table 'r_db.TableBase' doesn't exist
01:42:54,706 ERROR TableBaseEAO:67 - ::::::::EXCEPTION javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute query
I am not using any column called clazz_
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class TableBase {
#Id
#Column(name="NAME")
private String name;
#Column(name="PHONE")
private String phoneNumber;
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phone) {
this.phoneNumber = phone;
}
}
My entity class for table1
#Entity
#Table(name="TABLE_1")
public class Table1 extends TableBase {}
Entity class for table 2
#Entity
#Table(name="TABLE_2")
public class Table2 extends TableBase {}
following code is to get data in to the list from my 2 db tables
public ArrayList<TableBase> getUsers(){
AppEntityManager appEntMgr = AppEntityManager.getAppEntityManager();
appEntMgr.startTransaction();
return (ArrayList<TableBase>) appEntMgr.createQuery("select e from TableBase e")
.setFirstResult(0)
.setMaxResults(10)
.getResultList();
}

Eclipselink tries to inset null value in table

I'm currently trying to create a many to many mapping using eclipselink. Please note that for this specific example no table to resolve the relation is used (I kwon that this is not a good practice but it is necassary for this specific example).
I've created a database schema and the tables employee3 and insurance to map. The employee table holds a column called insurance_id which is part of the primary key in order to create the mapping. Same goes for insurance with employee_id.
Now for the code:
Here is the code for the two classes:
First off Employee:
#Entity
#Table(name="employee3", schema = "many_to_many")
public class EmployeeManyToMany
{
protected EmployeeManyToMany()
{
}
#Id
private int id;
private String firstName;
private String lastName;
#ManyToMany(cascade = CascadeType.PERSIST)
private Collection<InsuranceManyToMany> insurance;
public EmployeeManyToMany(int id, String firstName, String lastName)
{
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
insurance = new ArrayList<InsuranceManyToMany>();
}
.....
And Insurance:
#Entity
#Table(name = "insurance", schema = "many_to_many")
public class InsuranceManyToMany
{
#Id
#Column(name = "id")
private int insuranceId;
private String company;
#ManyToMany(mappedBy = "insurance", cascade = CascadeType.PERSIST)
private Collection<EmployeeManyToMany> employee;
protected InsuranceManyToMany()
{
}
public void addEmployee(EmployeeManyToMany emp)
{
employee.add(emp);
}
public InsuranceManyToMany(String company, int insuranceId)
{
this.insuranceId = insuranceId;
this.company = company;
employee = new ArrayList<EmployeeManyToMany>();
}
....
After I create an Employee object and add a list of insurances to it i try to persist it into the database.
Which results in the following error:
javax.persistence.RollbackException: Exception [EclipseLink-4002]
Eclipse Persistence Services - 2.7.3.v20180807-4be1041):
org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: null value
in column "insurance_id" violates not-null constraint
Detail: Failing row contains (1, hans, test, null).
Error Code: 0
Call: INSERT INTO many_to_many.employee3 (ID, FIRSTNAME, LASTNAME) VALUES
(?, ?, ?)
bind => [3 parameters bound]
Query: InsertObjectQuery(swd_ws18_06_Tag3.EmployeeManyToMany#88d98e)
I have no idea why this occures since the values are never null.
Any help is appreciated!
BR
Simon

Extend an entity class in JPA throws Unknown column 'DTYPE' in 'field list' error

#Entity
#Table(name = "PERSON")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Person {
#Id
#GeneratedValue
#Column(name = "PERSON_ID")
private Long personId;
#Column(name = "FIRSTNAME")
private String firstname;
#Column(name = "LASTNAME")
private String lastname;
// Constructors and Getter/Setter methods,
}
Employee class extends Person
#Entity
public class Employee extends Person {
#Transient
private Date joiningDate;
// Copy Constructors and Getter/Setter methods,
}
The Employee class has only a transient object So I am not sure about using of #DiscriminatorColumn and #DiscriminatorValue, When i tried without using Discriminator that throws error
session.save(employee);
I am trying to save Employee object that throws Unknown column 'DTYPE' in 'field list' error
I have encountered the same issue using EclipseLink and I have tried to use #discriminator annotation ... without success
because in this solution, a specific column must be added in 2 tables.
I don't have the possibility to add columns in tables, so I have found following solution :
#Entity
#Table(name = "PERSON")
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Person {
I have just changed inheritance type from SINGLE_TABLE to TABLE_PER_CLASS
I have found useful explanation on Thoughts on Java
Just for information, my 2 tables are in reality 1 table and a view on same table with 2 or 3 joins.
You should use #DiscriminatorColumn and #DiscriminatorValue. You can find a good example here.
D_TYPE is basically name of your child class.
Let's suppose you have:
Abstract Employee(id, name);
class FullTimeEmployee extends Employee(Double salary)
with Inheritence.SINGLE_TABLE strategy.
A table employee will be created with these columns
Employee (D_TYPE, id, name, salary)
where D_TYPE will be name of your child classes.
employeeRepository.insert(Employee emp);
where you can pass emp as new FullTimeEmployee(id, name, salary);
After insert it will automatically populate d_type as Full_Time_Employee
If you want to change the name of D_TYPE column use
#DiscriminatorColumn(name="customizedNameofD_TYPE")
Just FYI: mostly used strategy is InheritanceType.JOINED
Persist child entity rather than persisting parent entity.
#MappedSuperclass
public class Person {
And
#Entity
#Table(name = "PERSON")
public class Employee extends Person {
This should resolve your issue.

hibernate joined strategy inheritance and polymorphism

In hibernate, when I use the joined strategy. does hibernate support polymorphism?
for example:
#Entity
#Table(name = "PERSON")
#Inheritance(strategy=InheritanceType.JOINED)
public class Person {
#Id
#GeneratedValue
#Column(name = "PERSON_ID")
private Long personId;
#Column(name = "FIRSTNAME")
private String Fullname;
public Person() {
}
public Person(String fullname) {
this.Fullname= fullname
}
}
and the derived class:
#Entity
#Table(name="EMPLOYEE")
#PrimaryKeyJoinColumn(name="PERSON_ID")
public class Employee extends Person {
#Column(name="department_name")
private String departmentName;
public Employee() {
}
public Employee(String fullname, String departmentName,) {
super(fullname);
this.departmentName = departmentName;
}
}
also all the fields include the getter and setters.
so in my main, when I'll do this:
session.beginTransaction();
person e = new Employee();
e.setFullname("james");
e.setdepartmentName("R&D");
session.getTransaction().commit();
I know for a fact that if e was of Employee type, hibernate would have created a row for both Employee and Person tables.
but for this example will hibernate generate queries for person and employee?
in other words, will hibernate support the polymorphic behavior?
When I understand you question correctly than you want to know if hibernate does in that case automtically return Employees when you query for all Persons. Additionally if it inserts an Employee when the object is declared as Person p = new Employee().
Short answer to both yes. More detailed.
The insert operation is based on the actual type of the object and not on exactly the type written in your sourcecode.
Related to querying of Persons. Hibernate does left outer join all subtypes so you will get also Employess back when you do the following:
Query query = session.createQuery("From Person ");
List<Person> persons = query.getResultList();

could not set a field value by reflection setter

In a spring mvc application using hibernate and MySQL, I am getting an error which seems to indicate that a Name entity cannot find the setter for the id property of the BaseEntity superclass of the Patient entity.
How can I resolve this error?
Here is the error message:
Caused by: org.hibernate.PropertyAccessException: could not set a field value by
reflection setter of myapp.mypackage.Name.patient
Here is the line of code that triggers the error:
ArrayList<Name> names = (ArrayList<Name>) this.clinicService.findNamesByPatientID(patntId);
Here is the BaseEntity, which is the superclass of both Patient and Name:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#DiscriminatorFormula("(CASE WHEN dtype IS NULL THEN 'BaseEntity' ELSE dtype END)")
public class BaseEntity {
#Transient
private String dtype = this.getClass().getSimpleName();
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
protected Integer id;
public void setId(Integer id) {this.id = id;}
public Integer getId() {return id;}
public void setDtype(String dt){dtype=dt;}
public String getDtype(){return dtype;}
public boolean isNew() {return (this.id == null);}
}
Here is the Patient entity:
#Entity
#Table(name = "patient")
public class Patient extends BaseEntity{
#OneToMany(mappedBy = "patient")
private Set<Name> names;
protected void setNamesInternal(Set<Name> nms) {this.names = nms;}
protected Set<Name> getNamesInternal() {
if (this.names == null) {this.names = new HashSet<Name>();}
return this.names;
}
public List<Name> getNames() {
List<Name> sortedNames = new ArrayList<Name>(getNamesInternal());
PropertyComparator.sort(sortedNames, new MutableSortDefinition("family", true, true));
return Collections.unmodifiableList(sortedNames);
}
public void addName(Name nm) {
getNamesInternal().add(nm);
nm.setPatient(this);
}
//other stuff
}
Here is the Name entity:
#Entity
#Table(name = "name")
public class Name extends BaseEntity{
#ManyToOne
#JoinColumn(name = "patient_id")
private Patient patient;
public Patient getPatient(){return patient;}
public void setPatient(Patient ptnt){patient=ptnt;}
//other stuff
}
The complete stack trace can be viewed at this link.
The SQL generated by Hibernate for the above query is:
select distinct hl7usname0_.id as id1_0_0_, givennames1_.id as id1_45_1_,
hl7usname0_.family as family1_44_0_, hl7usname0_.patient_id as patient3_44_0_,
hl7usname0_.person_id as person4_44_0_, hl7usname0_.suffix as suffix2_44_0_,
hl7usname0_.usecode as usecode5_44_0_, hl7usname0_.codesystem as codesyst6_44_0_,
givennames1_.given as given2_45_1_, givennames1_.name_id as name3_45_1_,
givennames1_.name_id as name3_0_0__, givennames1_.id as id1_45_0__
from hl7_usname hl7usname0_
left outer join hl7_usname_given givennames1_ on hl7usname0_.id=givennames1_.name_id
where hl7usname0_.patient_id=1
When I run this query through the MySQL command line client, it returns the only record in the test database table.
That's not what the stack trace says. The stack trace doesn't say that the ID can't be set. It says:
Caused by: java.lang.IllegalArgumentException: Can not set org.springframework.samples.knowledgemanager.model.HL7Patient field org.springframework.samples.knowledgemanager.model.HL7USName.patient to org.springframework.samples.knowledgemanager.model.HL7USName
So, your HL7USName class has a field named patient of type HL7Patient, and it's impossible to set this field with a value of type HL7USName.
This means that your database contains a Name that has a foreign key to a row of type Name instead of a row of type Patient.

Categories

Resources