JPA - One to Many association without a join column - java

I would like to write a JPA entity class that has a one to many relationship. I would like to avoid defining the relationship in the parent class to avoid the data to be loaded every time a reference is made for the object even when there is no need for the associated data. I have read that even with Lazy loading, the data can be loaded so i need to avoid that.
In the following example,
Customer table
------------------------
customerid, customerName
1 John
2 Bob
Order Table - customerId is a foreign key to Customer
orderId, customerId, orderDate
1 1 12MAY2012
1 1 13MAY2012
1 2 16MAY2012
JPA Entities
#Entity
public class Customer {
// all Customer-related fields WITHOUT #OneToMany relationship with Order
}
#Entity
public class Order {
String orderDate;
#ManyToOne
private Customer owner;
}
How would i retrieve data from the customer table based on a condition on the order table? For example, how can i say "Get me all customers who have made an order where the orderDate is between two dates?

using hbm.xml there are query only properties to achieve what you want
http://ayende.com/blog/4054/nhibernate-query-only-properties

Related

Mapping Multiple Tables into a Single Entity in JPA

I'm trying to learn JPA/Hibernate and I'm real green in this field. I tend to usually veer off and try things without knowing much about the API. So I decided to create a simple entity that retrieves information from multiple tables see this is easily implementable with JPA. The reason behind this is, if, hypothetically, the involving tables each has a few hundred columns and we only have a business need to retrieve a very few data, and we only need to focus on retrieval rather than inserts/updates/deletions, I would assume it is best to only retrieve the entire entity (specially if multiple rows need to be returned) then join them across other entities to derive a few columns.
I started up with two simple tables:
EMPLOYEES
EMPLOYEE_ID, EMAIL, DEPARTMENT_ID, MANAGER_ID, FIRST_NAME, etc...
DEPARTMENTS
DEPARTMENT_ID, DEPARTMENT_NAME, MANAGER_ID, etc...
I want my entity to retrieve only the following columns solely based on EMPLOYEES.EMPLOYEE_ID:
EMPLOYEES.EMPLOYEE_ID
EMPLOYEES.MANAGER_ID
EMPLOYEES.DEPARTMENT_ID
DEPARTMENT.DEPARTMENT_NAME
One thing to notice here is that EMPLOYEES.MANAGER_ID is a self-referencing foreign key to EMPLOYEES.EMPLOYEE_ID.
I might create the following...
#SecondaryTable(name="DEPARTMENTS",
pkJoinColumns=#PrimaryKeyJoinColumn(name="managerId",referencedColumnName="employeeId")
)
#Table(name="EMPLOYEES")
#Entity
public class EmployeesDepartment {
#Id
private String employeeId;
private String managerId;
private String email;
private int departmentId;
#Column(name="DEPARTMENT_NAME",table="DEPARTMENTS")
private String departmentDesc;
// Setters and getters
}
Obviously this doesn't give us the correct answer due to the fact that the join between the secondary table (DEPARTMENTS) occurs between its MANAGER_ID and EMPLOYEES.EMPLOYEE_ID, rather than DEPARTMENTS.MANAGER_ID = EMPLOYEES.MANAGER_ID.
I cannot replace referencedColumnName="employeeId" with referencedColumnName="managerId" as managerId of #Entity EmployeesDepartment is not a primary key of EMPLOYEES.
And I can't do the following:
#OneToOne
#JoinColumn(name="managerId",table="DEPARTMENTS",referencedColumnName="employeeId")
private String managerId;
My question is, how can I make my join to be on DEPARTMENTS.MANAGER_ID = EMPLOYEES.MANAGER_ID while the WHERE clause of the query is based on EMPLOYEES.EMPLOYEE.ID? In other word, how can I have the entity that is mapped to the following query:
SELECT
E.EMPLOYEE_ID,
E.MANAGER_ID,
E.DEPARTMENT_ID,
D.DEPARTMENT_NAME
FROM EMPLOYEES E LEFT OUTER JOIN DEPARTMENTS D ON E.MANAGER_ID = D.MANAGER_ID
WHERE E.EMPLOYEE_ID = ?
Or are there better solution with less side effects, e.g. order of updates of tables, loading, etc.?

JPA persist one-to-one persistence with non-existing entity from one side

I have an old database where there are two tables with implicit association between them:
booking
- id
- name
... some other fields...
and
booking_info
- id
- booking_id
... some other fields...
Due to the current database design there no any constraints between these two tables, which means that one booking entry may exist without any booking_info entries and vice versa. booking_id in booking_info table is an implicit foreign key which refers to booking table (column id), but it also may refer to the absent booking.
I have created the following JPA mapping for these tables:
#Entity
public class Booking {
#Id
private Long id;
private String name;
// getters & setters
}
and
#Entity
public class BookingInfo {
#Id
private Long id;
#OneToOne
#JoinColumn(name = "booking_id")
private Booking booking
// getters & setters
}
Now I need to be able to persist a BookingInfo entity even if there's no related Booking entry in the database.
BookingInfo bookingInfo = new BookingInfo();
bookingInfo.setId(1);
Booking booking = new Booking();
booking.setId(182); // let's say that there's no booking with id 182 in my database, but I still need to persist this bookingInfo
bookingInfo.setBooking(booking);
bookingInfoRepository.save(bookingInfo); // using Spring Data JPA
If I run this code then I get javax.persistence.EntityNotFoundException since booking with id 182 is absent.
What would be the proper workaround for my case using JPA or Hibernate.
Btw, I also tried to use Hibernate's #NotFound annotation. As a result, save method doesn't throw javax.persistence.EntityNotFoundException and entity gets persisted int the database, but the problem is that booking_id in the database always null.
Any help would be appreciated.
I am not sure my answer will help you or not, but the result you are getting perfectly make sense. As you are setting a JPA object, and that object is not present, hence the null value is saved.
If you want to save 182 as an integer, you don't do JPA relationship. Instead, you just use booking-id as an integer field in booking-info. And that makes sense because you actually do not have the relationship between those tables which the JPA is trying to achieve.
But I am sure you just want to save 182 and as well as maintain the JPA relationship. And I am sure you already know it, but DB integrity is not being maintained with the approach you are taking. I am sure there is enough reason behind that. But my recommendation would be applying proper constraints in the DB and then in JPA.

Find entity filtered by a related entity that is in a collection

I'm using Spring Data JPA for my repository layer and spring security as my security layer. In my project, I have the following unidirectional one-to-many relationship between Department and Employee. Below are snippets of the 2 entities.
#Entity
public class Department {
...
#OneToMany
#JoinColumn(name="department")
private Set<Employee> members;
...
}
#Entity
public class Employee {
...
private String username;
...
}
The relationship has to be unidirectional due to certain restrictions and one of my use case is to find the department of a logged in user.
My question is, how do I filter out a Department entity based one the current user logged in (i.e. the current user logged in must match 1 Employee object via the username field) using either spring data query methods or jpql?
Using JPQL you can use MEMBER OF collection predicate.
//Fetch <YOUR EMPLOYEE ENTITY TO MATCH> or
//Create an new EMPLOYEE object with its primary key prepopulated if you already know it.
Query query = SELECT d FROM Department d WHERE :employee MEMBER OF d.members
query.setParameter("employee", <YOUR EMPLOYEE ENTITY TO MATCH>);
query.list();
I figured out how my requirement can be fulfilled via Spring Data JPA #Query approach without needing to compare with the Employee object but just the username.
#Query("select dept from Department dept inner join dept.members member where member.username = ?1")
Department findDeptByQuery(String username)

How do I insert comma separated value using Hibernate with MySQL?

How do I store integer type list in a comma-separated format in Hibernate?
For example - I have a city table where I have cityId and CityName. In another table I have employee details.An employee can be tagged with multiple city.
I have created another table for employee-city mapping where I want to store the cities in comma separated format.
Table- Employee
----------------------------
Employee_ID Employee_Name
1 Employee 1
2 Employee 2
Table -city
------------------------
City_ID City_Name
1 City_1
2 City_2
Table- Employee-City Mapping
-----------------------
Emp_ID City_id
1 1,2
2 1,2
How to do the this kind actions in Hibernate ? Please help. I am using MySQL as the database backend.
It looks like you are trying to represent a one-to-many relationship.
The conventional SQL way to represent a one-to-many relationship is via multiple rows in a join table. In your case the join table is the employee-city table with a modified design with multiple rows per city rather than multi-valued columns:
Table- Employee-City Mapping
-----------------------
Emp_ID City_id
1 1
1 2
2 1
2 2
JPA (which Hibernate supports) has direct support for mapping these relationships to Collection fields. Your Employee class would have a cities field with type List<City> annotated with #OneToMany.
#Entity
public class Employee {
#Id
#Column(name="Emp_ID")
private long id;
#OneToMany
#JoinColumn(name="Emp_ID", referencedColumnName="City_ID")
private List<City> cities;
// ... rest of the class: constructor, getters, setters
}
The following guide may also help:
https://en.wikibooks.org/wiki/Java_Persistence/OneToMany

Returning child entities from a parent entity with JPA join

How can I return a list of entities that has a relationship to a parent in JPA?
I have a User entity that has a #OneToMany mapping on a property named pets. The child entities are of type Pet. It is only a uni-directional relationship.
How can I write a join in JPA that returns all pets given a user?
So you have a couple of options.
You can use the following annotations:
#ManyToOne
#JoinColumn
This is how you would use it.
public class User
{
// your standard fields / columns in database
#OneToMany (Fetch can be of eager/ lazy)
#JoinColumn (name="column to join on", referencedColumnName="column to join on in parent class")
private List<Pet> pets;
}
public Class Pet
{
//data fields
}
What essentially happens is the list of pets is populated when you are querying for the user object.
Using JPA to Query the DB.
So i am guessing that Your user would have some sort of id and the pet table would have some sort of Id to the user that are linked.
So we would do the following
Select * from user where user_id = ?;
this will essentially give you the user object
Select * from pet where owner_user_id = ?
this will essentially give you all the pets that belong to that user.
Then you can populate your object yourself.
I am not 100% sure of how your table looks like, but I was hoping to give it a stab from just what I would do point of view.

Categories