I'm running into an issue with adding JOIN's to a subquery using DetachedCriteria. The code looks roughly like this:
Criteria criteria = createCacheableCriteria(ProductLine.class, "productLine");
criteria.add(Expression.eq("productLine.active", "Y"));
DetachedCriteria subCriteria = DetachedCriteria.forClass(Model.class, "model");
subCriteria.setProjection(Projections.rowCount());
subCriteria.createAlias("model.modelLanguages", "modelLang");
subCriteria.createAlias("modelLang.language", "lang");
criteria.add(Expression.eq("lang.langCode", "EN"));
subCriteria.add(Restrictions.eqProperty("model.productLine.productLineId","productLine.productLineId"));
criteria.add(Subqueries.lt(0, subCriteria));
But the logged SQL does not contain the JOIN in the subquery, but does include the alias which is throwing an error
SELECT *
FROM PRODUCT_LINE this_
WHERE this_.ACTIVE=?
AND ? <
(SELECT COUNT(*) AS y0_
FROM MODEL this0__
WHERE lang3_.LANG_CODE ='EN'
AND this0__.PRODUCT_LINE_ID =this_.ID
)
How can I add the joins to the DetachedCriteria?
#Entity
#Table(name = "PRODUCT_LINE")
public class ProductLine implements java.io.Serializable {
private long productLineId;
private char active;
private Set<Models> models = new HashSet<Models>(0);
#OneToMany(fetch = FetchType.LAZY, mappedBy = "productLine")
public Set<Models> getModels() {
return this.models;
}
}
#Entity
#Table(name = "MODEL")
public class Model implements java.io.Serializable {
private long modelId;
private ProductLine productLine;
private String name;
private Set<ModelLanguages> modelLanguages = new HashSet<ModelLanguages>(0);
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "PRODUCT_LINE_ID")
public ProductLine getProductLine() {
return this.productLine;
}
#Column(name = "NAME", nullable = false)
public String getName() {
return this.name;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "model")
public Set<ModelLanguages> getModelLanguages() {
return this.modelLanguages;
}
}
#Entity
#Table(name = "MODEL_LANGUAGES")
public class ModelLanguages implements java.io.Serializable {
private long id;
private Language language;
private Model model;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "LANGUAGE_ID", nullable = false, insertable = false, updatable = false)
public Language getLanguage() {
return this.language;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "MODEL_ID", nullable = false, insertable = false, updatable = false)
public Model getModel() {
return this.model;
}
}
#Entity
#Table(name = "LANGUAGES", uniqueConstraints = #UniqueConstraint(columnNames = "LANG_CODE"))
public class Language implements java.io.Serializable {
private long languageId;
private String langCode;
private Set<ModelLanguages> modelLanguages = new HashSet<ModelLanguages>(
0);
#Column(name = "LANG_CODE", unique = true, nullable = false)
public String getLangCode() {
return this.langCode;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "language")
public Set<ModelLanguages> getModelLanguages() {
return this.modelLanguages;
}
}
Hibernate version: 3.2.6.ga
Hibernate core: 3.3.2.GA
Hibernate annotations: 3.4.0.GA
Hibernate commons-annotations: 3.3.0.ga
Hibernate entitymanager: 3.4.0.GA
Hibernate validator: 3.1.0.GA
Don't you have a typo in your code at the following line :
criteria.add(Expression.eq("lang.langCode", "EN"));
I think, you should add this restriction on the subcriteria and not the criteria.
If you need to join tables in subquery can you try make this. It is explicitly specifying joinType in your detached criteria.
subCriteria.createAlias("model.modelLanguages", "modelLang", CriteriaSpecification.LEFT_JOIN);
subCriteria.createAlias("modelLang.language", "lang", CriteriaSpecification.LEFT_JOIN);
Related
OneToOne mapping not working: EntityA.entityB referencing EntityB not mapped to a single property
I have two entities, EntityA and EntityB.
EntityA has a composite primary key on two fields: id and flag.
EntityB also has a composite primary key on two fields: id and flag.
The two entities are linked with a common field / column: entityBKey. (This is a foreign key but not explicitly defined as such at the database level, if that makes a difference. Old design can't really change much)
This is how I am calling EntityA:
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<EntityA> criteriaQuery = builder.createQuery(EntityA.class);
Root<EntityA> from = criteriaQuery.from(EntityA.class);
criteriaQuery.select(from);
But I get this error on application boot:
EntityA.entityB referencing EntityB not mapped to a single property
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:203)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:104)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processEndOfQueue(InFlightMetadataCollectorImpl.java:1750)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processFkSecondPassesInOrder(InFlightMetadataCollectorImpl.java:1694)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1623)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:295)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:86)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:479)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:85)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:709)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:746)
In some places I have read it says that non-primary keys can be referenced by using the referencedColumnName attribute but it is clearly not working.
Any ideas what I can do here? Much appreciated.
EntityA:
#Entity
#Table(name = "EntityA")
#IdClass(KeyClass.class)
public class EntityA implements Serializable {
#Id
#Column(name = "id", nullable = false)
protected Integer id = null;
#Id
#Column(name = "flag", nullable = false)
protected Integer flag = null;
#Column(name = "EntityAKey", nullable = false)
private String entityAKey = null;
#Column(name = "EntityBKey", nullable = false)
private String entityBKey = null;
#OneToOne(mappedBy="entityA")
private EntityB entityB;
public EntityA() {
super();
}
}
EntityB:
#Entity
#Table(name = "EntityB")
#IdClass(KeyClass.class)
public class EntityB implements Serializable {
#Id
#Column(name = "id", nullable = false)
protected Integer id = null;
#Id
#Column(name = "flag", nullable = false)
protected Integer flag = null;
#Column(name = "EntityBKey", nullable = false)
private String entityBKey = null;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumns({
#JoinColumn(name = "entityBKey", referencedColumnName = "entityBKey", insertable = false, updatable = false),
#JoinColumn(name = "flag", referencedColumnName = "flag", insertable = false, updatable = false)}
)
#Where(clause = "flag=1")
private EntityA entityA;
public EntityB() {
super();
}
}
KeyClass:
public class KeyClass implements Serializable {
private Integer id = null;
private Integer flag = null;
public KeyClass() {
}
public KeyClass(Integer id, Integer flag) {
this.id = id;
this.flag = flag;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getFlag() {
return flag;
}
public void setFlag(Integer flag) {
this.flag = flag;
}
#Override
public boolean equals(Object o) {
...
}
#Override
public int hashCode() {
...
}
}
I am trying to understand and figure out the solution for the following use case
These are my entity classes
User
#Entity
#Table(name = "USER")
public class User {
private UserID id;
private Set<UserAddress> addresses = new HashSet<UserAddress>(0);
#EmbeddedId
#AttributeOverrides( {
#AttributeOverride(name = "userId", column = #Column(name = "USER_ID", nullable = false, length = 32)),
#AttributeOverride(name = "userType", column = #Column(name = "USER_TYPE", nullable = false, precision = 12, scale = 0)) })
public User getId() {
return this.id;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "user", cascade={CascadeType.ALL})
#BatchSize(size=50)
public Set<UserAddress> getAddresses() {
return this.addresses;
}
........
}
UserAddress
#Entity
#Table(name = "USERADDRESS")
public class UserAddress {
private UserID id;
Private User user;
private String address;
#EmbeddedId
#AttributeOverrides( {
#AttributeOverride(name = "userId", column = #Column(name = "USER_ID", nullable = false, length = 32)),
#AttributeOverride(name = "userType", column = #Column(name = "USER_TYPE", nullable = false, precision = 12, scale = 0)) })
public User getId() {
return this.id;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns( {
#JoinColumn(name = "userId", referencedColumnName = "USER_ID", nullable = false, insertable=false, updatable=false),
#JoinColumn(name = "userType", referencedColumnName = "USER_TYPE", nullable = false, insertable=false, updatable=false) })
public User getUser() {
return this.user;
}
........
}
UserId
#Embeddable
public class UserId implements Serializable {
private String userNo;
private Long UserType;
.......
.......
}
I have created a staticmetamodel class for User, UserID and UserAddress and created query based on Specifications.
Metamodel class for User
#StaticMetamodel(User.class)
public abstract class User_ {
public static volatile SetAttribute<User, UserAddress> addresses;
public static volatile SingularAttribute<User, UserID> id;
}
Metamodel for UserId
#StaticMetamodel(UserID.class)
public abstract class UserID_ {
public static volatile SingularAttribute<UserID, String> userNo;
public static volatile SingularAttribute<UserID, Long> UserType;
}
I am trying to retrieve maximum of 10 User objects ordered by UserType and searched based on userId. The query has to retrieve the UserAddresses as an eager fetch.
My Specification Object is
UserSpecification
public class UserSpecifications {
public static Specification<User> userNoIs(String userNo) {
return (root, query, cb) -> {
root.fetch(User_.addresses);
return cb.equal(root.get(User_.id).get(UserID_.userNo),userNo);
};
}
}
DAO Function:
Sort sortInstructions = new Sort(Sort.Direction.DESC, "id.userNo");
Pageable pageInfo = new PageRequest(0, maxCount, sortInstructions);
Specifications<User> specifications = Specifications.where(userNoIs(input.getUserNo()));
Page<User> responseList= userRepository.findAll(specifications,pageInfo);
I am getting the following exception when I run the above statement.
Caused by: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=generatedAlias1,role=com.entity.User.addresses,tableName=USERADDRESS ,tableAlias=useraddress1_,origin=USER user0,columns={user0.USER_TYPE user0.USER_ID ,className=com.entity.UserAddress}}]
But apart from that I also need to understand how to limit the no of rows returned using Specification but without using Pageable . If I use Pageable, then a separate query will be fired to retrieve the count of rows and then actual query is being fired. My application is performance oriented, and I do not want to have any extra queries being fired.
Is there any way where I can limit the no of rows without using Pageable, but using Specifications ?
I try to persist one parent entity which is joined with another child entity, but the problem is that the id is not generated for this child when persisting so I have this error : [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] ORA-01400: cannot insert NULL into ("L2S$OWNER"."SABRI"."TRANSITION_MATRIX_ID")
there is the child Entity :
#Data
#Entity
#IdClass(MyLibrarySabriEntityPK.class)
#Table(name = "SABRI", schema = "L2S$OWNER", catalog = "")
public class MyLibrarySabriEntity extends ActionForm {
#Access(AccessType.FIELD)
#Id
#ManyToOne
#JoinColumn(name = "TRANSITION_MATRIX_ID", referencedColumnName = "ID_TRANSITION_MATRIX")
private MyLibraryTestEntity sabriEntity;
#Id
private String RATING_ID_ROW;
#Id
private String RATING_ID_COL;
#Basic
#Column(name = "TRANSITION_PROBABILITY", nullable = true, insertable = true, updatable = true, precision = 20)
private Double TRANSITION_PROBABILITY;}
the PK class :
#Data
public class MyLibrarySabriEntityPK implements Serializable {
private String TRANSITION_MATRIX_ID;
private String RATING_ID_ROW;
private String RATING_ID_COL;
public MyLibrarySabriEntityPK(String TRANSITION_MATRIX_ID,String RATING_ID_COL,String RATING_ID_ROW ){
this.TRANSITION_MATRIX_ID=TRANSITION_MATRIX_ID;
this.RATING_ID_COL = RATING_ID_COL;
this.RATING_ID_ROW= RATING_ID_ROW;
}
}
there is the parent Entity:
#Data
#Entity
#Table(name = "TEST", schema = "L2S$OWNER", catalog = "")
public class MyLibraryTestEntity extends ActionForm {
#Access(AccessType.FIELD)
#OneToMany(mappedBy = "sabriEntity", cascade = CascadeType.PERSIST)
private final List<MyLibrarySabriEntity> entities = new ArrayList<MyLibrarySabriEntity>(25);
public void addEntitysabri(MyLibrarySabriEntity entity) {
getEntities().add(entity);
entity.setSabriEntity(this);
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "IdGenerated")
#GenericGenerator(name = "IdGenerated", strategy = "dao.Identifier")
#Column(name = "ID_TRANSITION_MATRIX", nullable = false, insertable = false, updatable = false, length = 10)
private String ID_TRANSITION_MATRIX;
#Basic
#Column(name = "REFERENCE", nullable = true, insertable = true, updatable = true, precision = 0)
private Integer reference;}
And here I try to persist the parent table which is supposed to persist also the child table but the Id is not generated !
MyLibrarySabriEntity Entity = null;
MyLibraryTestEntity test = getMyLibraryTestEntity(matrixStartDate, matrixName); // here I get the values of my entity test (parent)
try {
transaction.begin();
for (int row = 0; row < 20; row++) {
for (int col = 0; col < 20; col++) {
double val = cells.get(row + FIRST_ROW, col + FIRST_COL).getDoubleValue();
Entity = getMyLibrarySabriEntity(col, row, val); // this get the values of the Entity parameters (child)
Entity.setSabriEntity(test);
test.addEntitysabri(Entity);
em.persist(test);
}
}
} catch (Exception e) {
if (transaction.isActive())
transaction.rollback();
LOGGER.warn(e.getMessage(), e);
} finally {
if (transaction.isActive())
transaction.commit();
em.close();
}
Assuming you are using JPA 2.0+
Remove this mapping completely:
#Id
#Column(name = "TRANSITION_MATRIX_ID", nullable = false,
insertable = true, updatable = true, length = 100)
private String TRANSITION_MATRIX_ID;
and put the #Id directly on the ManyToOne and remove the insertable and updateable attributes.
#Access(AccessType.FIELD)
#Id
#ManyToOne
#JoinColumn(name = "TRANSITION_MATRIX_ID", referencedColumnName = "ID_TRANSITION_MATRIX")
private MyLibraryTestEntity sabriEntity;
Update your ID class accordingly. Any previous reference to TRANSITION_MATRIX_ID should be replaced with a reference to sabriEntity. You are also confusing #EmbeddedId and #IdClass: Only the former would contain column definitions whereas you are using the latter approach.
public class MyLibrarySabriEntityPK implements Serializable {
private String sabriEntity;
private String RATING_ID_ROW;
private String RATING_ID_COL;
}
See:
https://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#JPA_2.0
Thank's to Alan Hay, I found the problem , I change the property TRANSITION_MATRIX_ID of my IDclass to sabriEntity and I delete all the annotation of this class !
Child entity
#Data
#Entity
#IdClass(MyLibrarySabriEntityPK.class)
#Table(name = "SABRI", schema = "L2S$OWNER", catalog = "")
public class MyLibrarySabriEntity extends ActionForm {
#Access(AccessType.FIELD)
#ManyToOne
#Id
#JoinColumn(name = "TRANSITION_MATRIX_ID", referencedColumnName = "ID_TRANSITION_MATRIX")
private MyLibraryTestEntity sabriEntity;
#Id
private String RATING_ID_ROW;
#Id
private String RATING_ID_COL;
#Basic
#Column(name = "TRANSITION_PROBABILITY", nullable = true, insertable = true, updatable = true, precision = 20)
private Double TRANSITION_PROBABILITY;
Parent Entity
#Data
#Entity
#Table(name = "TEST", schema = "L2S$OWNER", catalog = "")
public class MyLibraryTestEntity extends ActionForm {
#Access(AccessType.FIELD)
#OneToMany(mappedBy = "sabriEntity", cascade = CascadeType.PERSIST)
private final List<MyLibrarySabriEntity> entities = new ArrayList<MyLibrarySabriEntity>(25);
public void addEntitysabri(MyLibrarySabriEntity entity) {
getEntities().add(entity);
entity.setSabriEntity(this);
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO, generator = "IdGenerated")
#GenericGenerator(name = "IdGenerated", strategy = "dao.Identifier")
#Column(name = "ID_TRANSITION_MATRIX", nullable = false, insertable = false, updatable = false, length = 10)
private String ID_TRANSITION_MATRIX;
#Basic
#Column(name = "REFERENCE", nullable = true, insertable = true, updatable = true, precision = 0)
private Integer reference;
PK Class
#Data
public class MyLibrarySabriEntityPK implements Serializable {
private MyLibraryTestEntity sabriEntity;
private String RATING_ID_ROW;
private String RATING_ID_COL;
public MyLibrarySabriEntityPK() {
}
public MyLibrarySabriEntityPK(MyLibraryTestEntity sabriEntity,String RATING_ID_COL,String RATING_ID_ROW ){
this.sabriEntity=sabriEntity;
this.RATING_ID_COL = RATING_ID_COL;
this.RATING_ID_ROW= RATING_ID_ROW;
}
}
Consider this scenario:
A Car can have a number of issues
An issue can be shared by a number of cars
I want to define this relationship using a Many-To-Many mapping with a join table.
And I want a generic column MODIFIED_TS to be maintained automatically on all three tables (yes - I can do it with database triggers - but that is not my ambition).
I have experimented with a variety of hibernate entity listeners and interceptors. They work fine - except for the join table.
Is there anyone out there who knows why callbacks like e.g. preInsert and onSave do not fire when rows are inserted or updated on the join table?
I am using:
Hibernate 4.3.10.Final
spring-data-jpa 1.8.1.RELEASE (does it matter?)
Base entity class:
#MappedSuperclass
public abstract class BaseEntity {
#Column(name = "MODIFIED_TS")
private Timestamp modifiedTs;
}
Car:
#Entity
#Table(name = "CAR")
public class Car extends BaseEntity {
#Id
#Column(name = "ID", nullable = false)
private long id;
#Column(name = "LICENSE_PLATE_NUMBER", nullable = false, length = 20)
private String licensePlateNumber;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "CAR_ISSUE", inverseJoinColumns = {#JoinColumn(name = "CAR_ID")},
joinColumns = {#JoinColumn(name = "ISSUE_ID")})
private Collection<Issue> issues;
}
Issue:
#Entity
#Table(name = "ISSUE")
public class Issue extends BaseEntity {
#Id
#Column(name = "ID", nullable = false)
private long id;
#Column(name = "TEXT", nullable = false, length = 2000)
private String text;
}
and CarIssue:
#Entity
#Table(name = "CAR_ISSUE")
public class CarIssue extends BaseEntity {
#Id
#Column(name = "ISSUE_ID", nullable = false)
private long issueId;
#Id
#Column(name = "CAR_ID", nullable = false)
private long carId;
}
My listener:
public class MyEntityListener implements PreUpdateEventListener, PreInsertEventListener {
public boolean setAudit(Object entity, String[] properties, Object[] state) {
if (entity instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) entity;
baseEntity.setModifiedTs(new Timestamp(new Date().getTime()));
List<String> propertiesList = Arrays.asList(properties);
state[propertiesList.indexOf("modifiedTs")] = baseEntity.getModifiedTs();
}
return false;
}
#Override
public boolean onPreInsert(PreInsertEvent event) {
return setAudit(event.getEntity(), event.getPersister().getPropertyNames(), event.getState());
}
#Override
public boolean onPreUpdate(PreUpdateEvent event) {
return setAudit(event.getEntity(), event.getPersister().getPropertyNames(), event.getState());
}
}
and finally this piece of code:
Car car = new Car();
car.setLicensePlateNumber("ABC123");
ArrayList<Issue> issues = new ArrayList<>();
Issue issue = new Issue();
issue.setDescription("Two wheels missing");
issues.add(issue);
car.setIssues(issues);
carRepo.save(car);
This works fine - I get a row in all three tables - but MODIFIED_TS only gets populated for CAR and ISSUE.
Any help is greatly appreciated:-)
I have four class; UserGroup, UserAccount, Role, UserGroupRoleRelation and my db is IBM DB2
#Entity
#Table(name = "USER_GROUP")
public class UserGroup implements Serializable {
#Id
#Column(name = "USER_GROUP_ID")
#GeneratedValue
private Long id;
......
..
#OneToMany(mappedBy = "userGroup", cascade = CascadeType.ALL, orphanRemoval = true)
private List<UserGroupRoleRelation> userAccountsRole = new ArrayList<UserGroupRoleRelation>();
}
#Entity
#Table(name = "ROLE")
public class Role implements Serializable {
#Id
#Column(name = "ROLE_ID")
#GeneratedValue
private Long id;
......
#OneToMany(mappedBy = "role")
private List<UserGroupRoleRelation> userAccountInGroup = new ArrayList<UserGroupRoleRelation>();
}
#Entity
#Table(name = "USER_GROUP_ROLE_LINE", uniqueConstraints = #UniqueConstraint(columnNames = { "ROLE_ID", "USER_GROUP_ID" }))
public class UserGroupRoleRelation {
#Id
#GeneratedValue
#Column(name = "RELATION_ID")
private Long relationId;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "USER_ACCOUNT_USER_GROUP_ROLE_LINE", joinColumns = { #JoinColumn(name = "RELATION_ID") }, inverseJoinColumns = { #JoinColumn(name = "USER_ID") }, uniqueConstraints = #UniqueConstraint(columnNames = { "USER_ID", "RELATION_ID" }))
private List<UserAccount> userAccountList = new ArrayList<UserAccount>();
#ManyToOne
#JoinColumn(name = "USER_GROUP_ID")
private UserGroup userGroup;
#ManyToOne
#JoinColumn(name = "ROLE_ID")
private Role role;
}
#Entity
#Table(name = "USER_ACCOUNT")
public class UserAccount implements Serializable {
#Id
#Column(name = "USER_ID")
#GeneratedValue
private Long id;
.....
#ManyToMany(mappedBy = "userAccountList", cascade = CascadeType.ALL)
private List<UserGroupRoleRelation> rolesInGroup = new ArrayList<UserGroupRoleRelation>();
}
I wanna find usergroups of a useraccount and i prepared a method with criteria. its like;
#Override
#Transactional
public List<UserGroup> findUserGroupOf(UserAccount userAccount) {
Criteria criteria = getSession().createCriteria(UserGroup.class);
criteria.createAlias("userAccountsRole", "userAccountsRole");
criteria.add(Restrictions.eq("userAccountsRole.userAccountList", userAccount));
return criteria.list();
}
But when i try to get result of that method, DB2 gives to me DB2 SQL Error: SQLCODE=-313, SQLSTATE=07004, SQLERRMC=null, DRIVER=3.63.75
Probably its about creating alias on many to many relation. I dont know what should i do to create alias on many to many. How can I get result of that function?
Thank
#Override
#Transactional
public List<UserGroup> findUserGroupOf(UserAccount userAccount) {
Criteria criteria = getSession().createCriteria(UserGroup.class);
criteria.createAlias("userAccountsRole", "userAccountsRole");
criteria.createAlias("userAccountsRole.userAccountList", "userAccountList");
criteria.add(Restrictions.eq("userAccountList.id", userAccount.getId()));
return criteria.list();
}
It works for me. I mean criteria on "id". But I don't understand why I cant check equality on object instead of id when there is ManyToMany list
It is not of creating alias. You are passing an object to hibernate on which it can not make any criteria. You need to create bidirectional mapping for that.Or else if you your requirement is just to fetch the the list of UserAccountList of particular UserGroup class you can follow the below code.
#Override
#Transactional
public List<UserGroup> findUserGroupOf(long userGroupId) {
Criteria criteria = getSession().createCriteria(UserGroup.class);
criteria.add(Restrictions.eq("id",userGroupId));
criteria.createAlias("userAccountsRole", "uar");
criteria.setFetchMode("uar.userAccountList",FetchMode.JOIN);
return criteria.list();
}