data not saved on join table - jpa

I generated entities using NetBeans (EclipseLink JPA) based on the following diagram:
The relevant generated code is:
Course
#JoinTable(name = "course_software", joinColumns = {
#JoinColumn(name = "course_id", referencedColumnName = "id", nullable = false)}, inverseJoinColumns = {
#JoinColumn(name = "software_id", referencedColumnName = "id", nullable = false)})
#ManyToMany
private List<Software> softwareList;
Software
#ManyToMany(mappedBy = "softwareList")
private List<Course> courseList;
The problem is with Course entity. When I try to persist it as follows
getFacade().create(currentCourse);
currentCourse.setSoftwareList(selectedSoftware);
then a record is created in course, but nothing is created in course_software join table.
How is this caused and how can I solve it?

It seems you don't need to specify the referencedColumnName attributes of #JoinColumn annotations as long as the columns referenced in the joined table are already primary keys.

Related

JoinColumns behavior for queries

I'm trying to understand if I can effect the sql query constructed by eclipselink based on my domain object's (Organization) #JoinColumns on a self-referencing Parent field.
#JoinColumns({
#JoinColumn(name = "PARENT_ID"),
#JoinColumn(name = "ORG_ID", referencedColumnName = "ORG_ID", nullable = false, updatable = false, insertable = false)
})
private Organization parent;
Reason for doing it is the query is faster when the join has both the parent_id and org_id.
Everything is fine until we try to query to find top-level organizations (Parent = null). The generated query has parent_id is null and org_id is null... this doesn't give us what we need. What am I doing wrong?

jpa OneToMany / ManyToOne how to save data

I'm learnig jpa and have a general question to saving data.
Suppose we have two entities:
Parent entity: Person
#JsonIgnore
#OneToMany(mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Car> cars = new HashSet<Car>();
Child entity: Car
#ManyToOne(fetch = FetchType.EAGER)
#JoinTable(name = "customer_car", joinColumns = #JoinColumn(name = "car_id"),
inverseJoinColumns = #JoinColumn(name = "person_id"))
private Person person;
The question is: What is the correct way to save data:
Person-Controller: I should use a #PostMapping to post a person with many cars.
Car-Controller: I should use a #PostMapping to post a car with many persons.
Option 1 and option 2 are possible

JPA one-to-one with secondary table for root entity

Following situation:
An root-Entity is build up from two database tables.
#Table("A")
#SecondaryTable(name="B", pkJoinColumns = {
#PrimaryKeyJoinColumn(name = "key1", referencedColumnName = "key1"),
#PrimaryKeyJoinColumn(name = "key2", referencedColumnName = "key2")})
The root entity contains an one-to-one association to an other entity lets call it "sub"
#OneToOne(fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name = "key1", referencedColumnName = "key1", updatable = false, insertable = false),
#JoinColumn(name = "KVSTU", referencedColumnName = "KVSTUFE", updatable = false, insertable = false),
#JoinColumn(name = "CODE_TARF_GEN", referencedColumnName = "TARIFGENERATION", updatable = false,
insertable = false)
})
private Sub sub;
Every thing works fine, but the JPA provider (in my case EclipseLink) doen't create an (outer) join. Instead of a join, for every dependend sub-entity an extra query is created.
I also tried pk join columns instead of join columns for the one-to-one association, with the same result.
What am I doing wrong?

JPA JoinColumns behaviour

class Employee {
#EmbeddedId
private EmployeeId id; // composite key with two fileds companyId and employeeNumber
#OneToMany(mappedBy = "employee", cascade = CascadeType.ALL)
private List<Phone> phoneList;
}
class Phone {
#EmbeddedId
private PhoneId phoneId; // composite key with three fileds companyId , employeeNumber and phoneNumber
#ManyToOne
#JoinColumns({
#JoinColumn(name = "COMPANY_ID", referencedColumnName = "COMPANY_ID", insertable = false,
updatable = false),
#JoinColumn(name = "EMPLOYEE_NUMBER_NEW", referencedColumnName = "EMPLOYEE_NUMBER",
insertable = false, updatable = false)})
private Employee employee;
}
In above example, Employee table gets generated with column employeeId, employeeNumber. And Phone table gets generated with employeeId, employeeNumber, phoneNumber, employee_nuber_new.
When I am creating employee object and phone object, at the end employeeId and employeeNumber values in Phone table gets populated from Employee object ( as part of FK ) but employee_number_new column still have "null" value. I want to updated employee_number_new column with employeeNumber from Employee table.
Tried lot of ways including JoinFormula and all but no success. Can anybody throw some light on this ?
Thanks...
The reason you are getting a null value in the Phone table because you are using insertable = false in your JoinColumn definition. If you could set this to true then your problem would be solved.
Hibernate doesn't support the mixing of insertable and non-insertable columns. So you have to make companyId insertable too. But that leads to the possibility of your primary key being changed in the Phone table which you don't want.
So, we are left with two options, if the EMPLOYEE_NUMBER is the same in both tables don't create the new column EMPLOYEE_NUMBER_NEW column and use EMPLOYEE_NUMBER.
But if EMPLOYEE_NUMBER is not the same in both tables then and you need to save the employee number from employee object, create another insertable column it can be COMPANY_ID_EMP and make updateable false. That way when you save a phone object both EMPLOYEE_NUMBER_NEW and COMPANY_ID_EMP will be saved. But in practice COMPANY_ID_EMP and COMPANY_ID will be the same value.
The following code worked for me
#ManyToOne
#JoinColumns({
#JoinColumn(name = "companyIdEmp", referencedColumnName = "companyId", updatable = false),
#JoinColumn(name = "employeeNumberNew", referencedColumnName = "employeeNumber", updatable = false)})
private Employee employee;

JPA join column only for insert/delete , disable select

I have #OneToMAny realationship inside my entity.
Is it possible to disable jpa from generating select for the joined column? beacuse I have many records in my main table and when selecting them , each record performs select for the joined column. I would like to disable this select is that possible?
UPDATE:
I tried inserting fetch LAZY but it still creates a select for Table02f and Table03f...
This is my code:
public class Table01f implements Serializable {
#OneToMany(fetch=FetchType.LAZY , cascade = CascadeType.ALL, mappedBy = "table01f")
private List<Table02f> table02fList;
//getter & setter...
}
public class Table02f implements Serializable {
#JoinColumn(name = "F2PRP", referencedColumnName = "F1PRP", insertable = false, updatable = false)
#ManyToOne(optional = false)
#JsonIgnore
private Table01f table01f;
#OneToMany(fetch=FetchType.LAZY , cascade = CascadeType.ALL, mappedBy = "table02f")
private List<Table03f> table03fList;
//getter & setter...
}
public class Table03f implements Serializable {
#JoinColumns({
#JoinColumn(name = "F3PRP", referencedColumnName = "F2PRP", insertable = false, updatable = false),
#JoinColumn(name = "F3BRN", referencedColumnName = "F2BRN", insertable = false, updatable = false)})
#ManyToOne(optional = false)
#JsonIgnore
private Table02f table02f;
//getter & setter...
}
Thank's In Advance.
Just add the fetch type LAZY to your #OneToMany relationship:
#OneToMany(fetch=FetchType.LAZY)
When you load the list of your main entities, JPA won't populate your list for this relationship, avoiding the generation of the SELECT.
Just have a look at this functionality in JPA documentation so that you can understand how to use it.
If you don't need the data make it LAZY (in general always make everything LAZY).
If you need the data, then you can use batch fetching, or join fetching.
http://java-persistence-performance.blogspot.com/2010/08/batch-fetching-optimizing-object-graph.html