HQL: Hibernate query with ManyToMany - java

I have a question with HQL query and hibernate.
I have a user class and a role class. A user can have many roles. So I have a ManyToMany relatation like this:
In user class:
#ManyToMany(fetch = FetchType.LAZY)
#oinTable(name = "PORTAIL_USERROLE", joinColumns = { #JoinColumn(name = "USERID", nullable = false, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "ROLE", nullable = false, updatable = false) })
public Set<Portailrole> getPortailroles() {
return this.portailroles;
}
In role class:
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "PORTAIL_USERROLE", joinColumns = { #JoinColumn(name = "ROLE", nullable = false, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "USERID", nullable = false, updatable = false) })
public Set<Portailuser> getPortailusers() {
return this.portailusers;
}
This mapping has created a 3rd table (PORTAIL_USERROLE) where relations are stocked.
All work fine like this. When I have a user, I retrieve roles.
But, my question is: in a HQL query, how can I get all users which have a specific role ? Any class represents PORTAIL_USERROLE table so I don't know how to make my HQL query.

This should do it:
from Portailuser u join u.portailroles r where r.name=:roleName

you can use
#WhereJoinTable
Like this:
#JoinTable(name = "OFFICE_USER_POSITION", joinColumns = {
#JoinColumn(name = "user_id", referencedColumnName = "id")}, inverseJoinColumns = {
#JoinColumn(name = "POST_ID", referencedColumnName = "id")})
#WhereJoinTable(clause = "primary_flag='" + YES + "' and del_flag='" + DEL_FLAG_NORMAL + "'")

Related

Preventing circular JSON conversions on ManyToMany entities

I am converting JPA entities to JSON for a REST API. Several of the entities have ManyToMany relationships which can cause recursion in the conversion process. I understand how to use #JsonIgnoreProperties to prevent recursion on the ManyToOne relationship, but not ManyToMany. Any guidance appreciated. Here is an example:
#ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST,CascadeType.DETACH})
#JoinTable(name = "insurance_companycodes", joinColumns = {
#JoinColumn(name = "insurance_id", referencedColumnName = "id", nullable = false, updatable = false) }, inverseJoinColumns = {
#JoinColumn(name = "insuranceCompanyCode_id", referencedColumnName = "id", nullable = false, updatable = false) })
private Set<InsuranceCompanyCode> insuranceCompanyCodes = new HashSet<>();

Double self-reference within the same entity using an extra join table

I want to create a double self-reference entity using an extra join table. I tried thus the following :
#Entity
#Table(name = "entity_a", schema="schema_a")
public class EntityA{
#Id
#Column(name = "id", unique = true, nullable = false)
private UUID id = UUID.randomUUID();
//skipped source code...
#OneToOne(fetch = FetchType.LAZY)
#JoinTable(name = "origin_child",
joinColumns =
{ #JoinColumn(name = "origin_id", referencedColumnName = "id", nullable = false)},
inverseJoinColumns =
{ #JoinColumn(name = "child_id", referencedColumnName = "id", nullable = false)})
private EntityA child;
#OneToOne(fetch = FetchType.LAZY)
#JoinTable(name = "origin_child",
joinColumns =
{ #JoinColumn(name = "child_id", referencedColumnName = "id", nullable = false)},
inverseJoinColumns =
{ #JoinColumn(name = "origin_id", referencedColumnName = "id", nullable = false)})
private EntityA origin;
//skipped source code...
}
When running my code I get the following error : org.hibernate.boot.spi.InFlightMetadataCollector$DuplicateSecondaryTableException: Table with that name [origin_child] already associated with entity
I tried thus to remove the origin field from EntityA and it worked. Now I am trying to figure out a way to join my EntityA.id and EntityA.origin_id over the already existing origin_child.child_id and origin_child.origin_id. Any idea how may I achieve that. Any alternative or better solution is more than welcome.
UPDATE :
I have tried the #JoinColumn alternative as following :
#OneToOne(fetch = FetchType.LAZY, mappedBy = "child")
private EntityA origin;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "child_id", referencedColumnName = "id", nullable = true)
private EntityA child;
Now when trying to update both origin and child instances :
child.setOrigin(origin);
entityARepository.save(child);
origin.setChild(child);
entityARepository.save(origin);
I get java.lang.StackOverflowError due to infinite recursion.
Any work around please?

Hibernate: multiple #ManyToMany relations in a single table

I have a project where Hibernate is used to manage entities. Multiple #ManyToMany relations can exists between two tables. So basically i have code like this:
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "movies_screenplay_authors",
joinColumns = #JoinColumn(name = "movie_id", nullable = false, updatable = false),
inverseJoinColumns = #JoinColumn(name = "staff_id", nullable = false, updatable = false))
private Set<Staff> screenplayAuthors = Sets.newHashSet();
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "movies_story_authors",
joinColumns = #JoinColumn(name = "movie_id", nullable = false, updatable = false),
inverseJoinColumns = #JoinColumn(name = "staff_id", nullable = false, updatable = false))
private Set<Staff> storyAuthors = Sets.newHashSet();
Now, I would like to store those relations inside a single table, with some additional column describing relation type. So basically, I would like to have something like this (pseudo-code used):
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "movies_staff",
joinColumns = #JoinColumn(name = "movie_id", nullable = false, updatable = false),
inverseJoinColumns = #JoinColumn(name = "staff_id", nullable = false, updatable = false),
joinCriteria = #JoinCriteria(columnName = "staff_type", value = StaffType.SCREENPLAY_AUTHOR, enumType = EnumType.STRING))
private Set<Staff> screenplayAuthors = Sets.newHashSet();
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "movies_staff",
joinColumns = #JoinColumn(name = "movie_id", nullable = false, updatable = false),
inverseJoinColumns = #JoinColumn(name = "staff_id", nullable = false, updatable = false),
joinCriteria = #JoinCriteria(columnName = "staff_type", value = StaffType.STORY_AUTHOR, enumType = EnumType.STRING))
private Set<Staff> storyAuthors = Sets.newHashSet();
Is this even possible, in Hibernate, or anywhere in Java world?
You can add after each #JoinTable annotation something like this:
#Fetch(FetchMode.SUBSELECT)
And its all.

Hibernate ManyToOne relation with multiple JoinColumn is not lazy fetched

I have a following example I want to create a lazy #ManyToOne relation between Car and CarAchievement tables using multiple join columns (example of class below)
#Entity
#Table(name = "CAR")
public class Car implements Serializable {
#Id
#GenericGenerator(name = "SEQ_CAR", strategy = "sequence",
parameters = {
#org.hibernate.annotations.Parameter(
name = "sequence",
value = "SEQ_CAR"
)
}
)
#GeneratedValue(generator = "SEQ_CAR")
#Column(name = "ID")
private Integer id;
#ManyToOne(fetch = FetchType.LAZY)
#NotFound(action = NotFoundAction.IGNORE)
#JoinColumns({
#JoinColumn(name = "region", referencedColumnName = "region", updatable = false, insertable = false),
#JoinColumn(name = "model", referencedColumnName = "model", updatable = false, insertable = false),
#JoinColumn(name = "year", referencedColumnName = "type", updatable = false, insertable = false),
#JoinColumn(name = "type", referencedColumnName = "year", updatable = false, insertable = false)
})
#JsonIgnore
private CarAchievement carAchievement;
}
This relation works fine but it seems not to be a LazyFetch, every query for a CAR seems to be fetching CarAchievement automatically even when its not specified to fetch this relation
Hibernate version: 4.3.10.Final

mappedBy and joinTable in wrong class

I used seam to generate my entities. But I have a many to many composite table with an employee id and a vehicle id and it generated the hash sets wrong. I want to be able to choose an employee's favorite vehicle in the employee object. However; when I add things to the hashset in the employee object and persist it, it does not add anything to the composite table. The vehicle object has the
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "flower_store_emp_vehicle", schema = "dbo", catalog = "tyler", joinColumns = { #JoinColumn(name = "vehicle_id", nullable = false, updatable = false) }, inverseJoinColumns = { #JoinColumn(name = "employee_id", nullable = false, updatable = false) })
and the employee object has the:
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "flowerStoreEmployees")
I am guessing these are backwards, however; I am new to seam and do not how to switch them around without the mappedBy being all wrong. If anyone knows how to help it would be greatly appreciated. Thank you
If you want the employee to be the owner of the association, just switch the annotations:
Employee:
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "flower_store_emp_vehicle",
schema = "dbo",
catalog = "tyler",
inverseJoinColumns = { #JoinColumn(name = "vehicle_id", nullable = false, updatable = false) },
joinColumns = { #JoinColumn(name = "employee_id", nullable = false, updatable = false) })
private Set<Vehicle> vehicles;
Vehicle:
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "vehicles")
private Set<Employee> employees;

Categories

Resources