So I have 2 tables. A users table and a finished_exams table. The finished_exams table has a user_id as foreign key and is related as OneToOne with the users table.
I made the relation in Users model like this:
#OneToOne(fetch = FetchType.EAGER, mappedBy = "user")
private FinishedExam finishedExam;
And in the FinishedExams model like this:
#OneToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "user_id")
private User user;
When I call all finished exams like this in the controller:
#GetMapping("/all")
public Iterable<FinishedExam> getAllFinishedExams()
{
return finishedExamRepository.findAll();
}
I get all Finishedexams linked with the users which is good.
My question is, is it possible to get ALL users with their finishedExam if they have it and without if they don't (So basically a LEFT JOIN)
Is this possible in Hibernate?
EDIT:
I just tried this but it only returns all users without the exams.
#GetMapping("/allUsersWithExams")
#Fetch(FetchMode.SELECT)
public Iterable<User> getAllUsersWithTheirExams()
{
return userRepository.findAll();
}
First of all sure is possible, you just have to write the query yourself:
"Select u from Users u LEFT JOIN u.finishedExam"
simple enough.
But what's stopping you to just select all user and get all their finished exam?
public Iterable<Users> getAllUsers()
{
return UsersRepository.findAll();
}
It will give you a list of all Users independently from having or not any finishedExam
Related
Hi I am new to Hibernate and trying to build a Rest APP.
I have 3 tables in the database as shown in the above image.
USERS table has ManyToMany relation with GROUPS table and USER_GROUP is an association table.
I am using ORM, Hibernate and CurdRepository.
I am able to insert into users table and group table with save() method of CurdRepository.
Now I am trying to add a row in GROUPS table and USER_GROUP table only. Can anyone lead me to the right direction?
For example:
I want to add an groupid to GROUPS table and then associate it with an user id
Let's say I want to insert (10) groupid in GROUPS and (14,10) in USER_GROUP table.
Is it doable with ORM, if yes how?
Thanks in advance
To use existing connecting table, USE_GROUP, User entity will be like following .
#Entity
public class Users {
#Id
private Integer userid;
private String password;
#ManyToMany(cascade = { CascadeType.MERGE, CascadeType.PERSIST })
#JoinTable(name = "USER_GROUP", joinColumns = { #JoinColumn(name = "USERID") },
inverseJoinColumns = { #JoinColumn(name = "GROUPID") })
private Set<Groups> groups;
// Getter, Setter
}
And then client code, add new User and Group, will be something like below.
User user = new User()
// set password , etc
Set<Groups> groups = new HashSet<>();
Group group = new Group();
// set
groups.add(group);
user.setGroups(groups);
userRepository.save(user);
There are many articles online about exactly this model to showcase how to use Hibernate. Here is one article I quickly found by googling for "hibernate user group example": https://www.codejava.net/frameworks/hibernate/hibernate-many-to-many-association-annotations-example
How do you make a select statement or filter a List that is nested within an entity in spring? I have an object that looks like this...
#Entity
#Table(name = "employee")
public class Employee {
...
#OneToMany(mappedBy = "_employee", fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
#JsonManagedReference
Set<Deal> _deals;
#OneToMany(mappedBy = "_employee", fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
#JsonManagedReference //This is simply to avoid a stackoverflow error according to this link http://stackoverflow.com/questions/3325387/infinite-recursion-with-jackson-json-and-hibernate-jpa-issue
Set<Recommendation> _recommendations;
#OneToMany(mappedBy = "_employee", fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
#JsonManagedReference //This is simply to avoid a stackoverflow error according to this link http://stackoverflow.com/questions/3325387/infinite-recursion-with-jackson-json-and-hibernate-jpa-issue
Set<Event> _events;
public Employee() {
}
//getters and setters
....
I get employees with a repository that is accessed by a service class.
The repository looks like this.
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
public Employee getEmployeeById(Long _id);
public Employee getEmployeeBy_username(String username);
}
So bascially when I get an employee by its id, it returns the above lists. When an employee is retrieved I need to do a select statement or filter in some way _deals, _recommendations and _events. So that only those who have the boolean attribute _active=true returned. As it is now, all deals recommendations and events are returned whether they are active or not. How do I filter or select from these lists only active objects?
You almost always select a single Entity type per query, and preferably you would do the filtering in the database. If you want the Deals, Recommendations and Events belonging to a specific Employee, I would normally put these methods in the Repository belonging to entity type I'm trying to load, it could look like this:
#Repository
public interface DealRepository extends JpaRepository<Deal, Long> {
#Query("select d from Deal d where d.active= true and d.employee.id = :employeeId")
List<Deal> findActiveDeals(#Param("employeeId") long employeeId);
}
I have two objects User and Workorder. One user can have multiple work orders. The problem is when I delete user it also deletes assigned work orders to that user. I have tried to set my work orders foreign keys to NULL before deleting the user but it still deletes all the associated work orders with that user. I'd like to delete user without deleting the work order assigned to user. What am I missing or doing wrong?
Here's is my User class:
#OneToMany(fetch = FetchType.LAZY, mappedBy="user", orphanRemoval=true)
private Set<WorkOrder> workOrder;
WorkOrder class:
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="user_id", nullable = true)
private User user;
UserDAOImpl class:
#Override
public void deleteUser(int theId) {
// get the current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// delete object with primary key
User user = currentSession.get(User.class, theId);
Set workorders = user.getWorkOrder();
Iterator<WorkOrder> work = workorders.iterator();
while (work.hasNext()){
WorkOrder workorder = work.next();
workorder.setUser(null);
}
currentSession.remove(user);
}
Remove that 'orphanRemoval=true' and check there's no 'cascade' on Workorder.user (if the relation is bidirectional)
I'm working on some personal project but i have a question about hibernate.
I have a class structure like this :
#Entity
public class User {
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "fkIdCompanyUser")
private Company company = new Company();
}
But inside the company i have another join.
#Entity
public class Company {
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "fkIdCompanyEstimateOption")
private EstimateOptions estimateOptions = new EstimateOptions();
}
Now i do a query to get the estimate options.
But if i do it like this it loads lots of unnecessary stuff .
#RequestMapping(value = "/estimateoptions")
public EstimateOptions getCompanyEstimateOptions(#AuthenticationPrincipal Principal user) {
User getuser = userDao.findByEmail(user.getName());
EstimateOptions estimateOptions = getuser.getCompany().getEstimateOptions();
return estimateOptions;
}
is there a better approach for this ?
There are a lot of ways to do such optimization. The simplest one is add bidirectional associations to Company and EstimateOptions with lazy loading.
An example for Company ( I don't test. It is just a sketch.)
#Entity
public class Company {
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "fkIdCompanyEstimateOption")
private EstimateOptions estimateOptions = new EstimateOptions();
#OneToOne(mappedBy="company", fetch = FetchType.LAZY)
private User user;
}
And do something like this (this is HQL but you can use a criteria API too)
from EstimateOptions options inner join options.company company inner join company.user user where user.name = :userName
You can see HQL joined query to eager fetch a large number of relationships for additional thoughts.
Updated
I am not sure but may be you can do something like this (without additional associations)
select options from User user inner join user.company company inner join company.estimateOptions options where user.name = :userName
I have two entities, User and Event. Each event can have multiple users associated with it, so its a one to many between Event and User.
The way its being stored in the database, is that I have 3 tables, user, event, and event_user. event_user contains 3 fields, id, eventId, userId. So I can do a query like select userId from event_user where eventId = ? to get all the users which are associated with the event.
My question is, how can I map this relationship between the events and users in Hibernate, to get it to auto save/load the users associated with the event? I want to have the following field in the Event class:
Set<User> users = new HashSet<>();
and have hibernate auto load / save the users to this set.
How can I map this (using annotations)?
Use the #ManyToMany annotation.
class Event{
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name = "EVENT_USER",
joinColumns = { #JoinColumn(name = "EVENT_ID") },
inverseJoinColumns = { #JoinColumn(name = "USER_ID") })
private Set<Users> users = new HashSet<Users>();
}
For more information on many to many associations in JPA check out this video tutorial at my blog.
Hibernate doc on the Bidirectional mapping using annotations should help
Basically you need to do something like this
#Entity
public class User implements Serializable {
#ManyToMany(
targetEntity=org.hibernate.test.metadata.manytomany.Event.class,
cascade={CascadeType.ALL}
)
#JoinTable(
name="USER_EVENT",
joinColumns=#JoinColumn(name="USER_ID"),
inverseJoinColumns=#JoinColumn(name="EVENT_ID")
)
public Set<Event> getEvents() {
return events;
}
...
}
#Entity
public class Event implements Serializable {
#ManyToMany(
cascade = {CascadeType.ALL},
mappedBy = "events",
targetEntity = User.class
)
public Set<User> getUsers() {
return users;
}
}