table Student
----------------
id | somecolumn with string| fk(which is self referencing ID of the same table)
how can i make hibernate query that will fetch all items where value of id will match value of fk.
here is what i have tried but it doesn't works (it returns only 1 result instead of result set)
List<Student> list = (List<Student>) sessionFactory
.getCurrentSession()
.createQuery("from Student p join p.studentFKs p2 where p2.id = :parentId")
.setParameter("parentId", parentId).list();
can someone help me solve the mistery? i know that it can be achieved with Hibernate criterias also.
UPDATE answer is to change query to(join was invalid.. ):
select p from Student p join p.student p2 where p2.id = :parentId
i use something like this and this is work
property of join inside entity Student :
#ManyToMany(cascade = CascadeType.REFRESH)
private Set<Student> testJoins = new HashSet<Student>();
HQL to get that set :
select a.testJoins from Student a where a.id = :parentId
maybe you can change your query from p2.id = :parentId to-->> p.id = :parentId
Related
I have this diagram:
table diagram
and I want to filter by the employees that have a project.
In normal SQL I will go like this
select * from employees e
join employee_projects ep on ep.employee_id = e.id
How can I achieve the same with Hibernate?
I tried using criteria builder and specifications but I can't get the data from the join table.
You can select all employees that have a project like this
em.createQuery(
"SELECT e FROM Employee e JOIN e.projects p WHERE p IS NOT NULL", Employee.class).getResultList()
You can join tables using join method of root object.
try something like this below
I have used it for one to many relation
Join<Post, Tag> join = root.join("tags", JoinType.INNER);
Predicate tagPredicate = criteriaBuilder.like(join.get("name"), "%" + search + "%");
for many to many relation,
Join<Post, Tag> postTagsTable = root.join("tags", JoinType.INNER);
return postTagsTable.<String>get("name").in(tagNames);
here I have tags field in Post entity, which is used inside join
I have a query that uses a constructor expression. For the most part it works, but I wanted to reduce the number of queries on the database. So I tried FETCH and #EntityGraph, but I am getting
org.springframework.dao.InvalidDataAccessResourceUsageException: 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 ...
I tried removing the FETCH and just use JOIN to fix the problem, but it does not do the fetch operation.
Is this even allowed or possible with Hibernate/JPA?
Code wise it looks something like
#Query("select new example.BillingTargetAndStudent(bt,s) from Student s, BillingTarget bt where s.id = bt.targetID and bt.account.status = :accountStatus and bt.account.organization = :organization")
Stream<BillingTargetAndStudent> streamAllByOrganizationAndStatusForStudentList(Organization organization, AccountStatus accountStatus);
What I want to do is FETCH bt.account in the same query along with s.user.attributes. The bt.account isn't too hard to workaround, but the s.user.attributes would not be possible with the constructor expression as it is a collection
What I ended up doing is to use the Stream<Object[]> and select bt, s from ... then have a converter that changes Object[] to call the constructor expression
default Stream<BillingTargetAndStudent> streamAllByOrganizationAndStatusForStudentList(Organization organization, AccountStatus accountStatus) {
return streamAllByOrganizationAndStatusForStudentList0(organization, accountStatus)
.map(o -> new BillingTargetAndStudent((BillingTarget) o[0], (Student) o[1]));
}
#Query("select bt, s from Student s join fetch s.user u join fetch u.attributes, BillingTarget bt join fetch bt.account a where s.id = bt.targetID and bt.account.status = :accountStatus and bt.account.organization = :organization")
Stream<Object[]> streamAllByOrganizationAndStatusForStudentList0(Organization organization, AccountStatus accountStatus);
I can reduce the query slightly by putting in one #EntityGraph
#EntityGraph("Student.forStudentList")
#Query("select bt, s from Student s, BillingTarget bt left join fetch bt.billingContractTargets bct join fetch bt.account a where s.id = bt.targetID and bt.account.status = :accountStatus and bt.account.organization = :organization")
Stream<Object[]> streamAllByOrganizationAndStatusForStudentList0(Organization organization, AccountStatus accountStatus);
#NamedEntityGraph(
name = "Student.forStudentList",
attributeNodes = {
#NamedAttributeNode("schedules"),
#NamedAttributeNode(value = "user", subgraph = "user.attributes"),
},
subgraphs = {
#NamedSubgraph(name = "user.attributes",
attributeNodes = {#NamedAttributeNode("attributes")})
}
)
But I am limited to just one and it has to be the entity for the repository. I cannot say
#EntityGraph("BillingTarget.forStudentList")
#EntityGraph("Student.forStudentList")
select s.student_name, teach from STUDENTS_TEACHER as sl
inner join STUDENT as s on sl.id = s.stud_id
inner join TEACHER as teach on sl.id = teach.teach_id
I am trying to get StudentName and Teacher.class entity in the above query.
Here STUDENTS_TEACHER is mapping each Student_id with Teacher_Id
How can I get the same using CriteraBuilder
Root<StudentTeacherMapping> studentTeacherMapping =criteriaQuery.from(StudentTeacherMapping.class);
Join<StudentTeacherMapping, Student> studentJoin = attributeCategoryMappingRoot.join("student");
Join<StudentTeacherMapping, Teacher> teachJoin = attributeCategoryMappingRoot.join("teacher");
criteriaQuery.multiselect(studentJoin.get("StudentName"), Teacher.get("TeacherSub"), ? );
How can I get the Teacher Object for here?
I have an #Entity class Company with several attributes, referencing a companies Table in my db. One of them represents a Map companyProperties where the companies table is extended by a company_properties table, and the properties are saved in key-value format.
#Entity
#Table(name = "companies")
public class Company extends AbstractEntity {
private static final String TABLE_NAME = "companies";
#Id
#GeneratedValue(generator = TABLE_NAME + SEQUENCE_SUFFIX)
#SequenceGenerator(name = TABLE_NAME + SEQUENCE_SUFFIX, sequenceName = TABLE_NAME + SEQUENCE_SUFFIX, allocationSize = SEQUENCE_ALLOCATION_SIZE)
private Long id;
//some attributes
#ElementCollection
#CollectionTable(name = "company_properties", joinColumns = #JoinColumn(name = "companyid"))
#MapKeyColumn(name = "propname")
#Column(name = "propvalue")
private Map<String, String> companyProperties;
//getters and setters
}
The entity manager is able to perform properly find clauses
Company company = entityManager.find(Company.class, companyId);
However, I am not able to perform JPQL Queries in this entity and retrieve the Map accordingly. Since the object is big, I just need to select some of the attributes in my entity class. I also do not want to filter by companyProperties but to retrieve all of them coming with the proper assigned companyid Foreign Key. What I have tried to do is the following:
TypedQuery<Company> query = entityManager.createQuery("SELECT c.id, c.name, c.companyProperties " +
"FROM Company as c where c.id = :id", Company.class);
query.setParameter("id", companyId);
Company result = query.getSingleResult();
The error I get is:
java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager:
Exception Description: Problem compiling [SELECT c.id, c.name, c.companyProperties FROM Company as c where c.id = :id]. [21, 40] The state field path 'c.companyProperties' cannot be resolved to a collection type.
org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1616)
org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1636)
com.sun.enterprise.container.common.impl.EntityManagerWrapper.createQuery(EntityManagerWrapper.java:476)
Trying to do it with joins (the furthest point I got was with
Query query = entityManager.createQuery("SELECT c.id, c.name, p " +
"FROM Company c LEFT JOIN c.companyProperties p where c.id = :id");
does not give me either the correct results (it only returns the value of the property and not a list of them with key-value).
How can I define the right query to do this?
Your JPA syntax looks off to me. In your first query you were selecting individual fields in the Company entity. But this isn't how JPA works; when you query you get back the entire object, with which you can access any field you want. I propose the following code instead:
TypedQuery<Company> query = entityManager.createQuery("from Company as c where c.id = :id", Company.class);
query.setParameter("id", companyId);
Company result = query.getSingleResult();
Similarly, for the second join query I suggest the following code:
Query query = entityManager.createQuery("SELECT c" +
"FROM Company c LEFT JOIN c.companyProperties p WHERE c.id = :id");
query.setParameter("id", companyId);
List<Company> companies = query.getResultList();
The reason why only select a Company and not a property entity is that properties would appear as a collection inside the Company class. Assuming a one to many exists between companies and properties, you could access the propeties from each Company entity.
You are expecting to get a complete Company object when doing select only on particular fields, which is not possible. If you really want to save some memory (which in most cases would not be that much of a success) and select only some field, then you should expect a List<Object[]>:
List<Object[]> results = entityManager.createQuery("SELECT c.id, c.name, p " +
"FROM Company c LEFT JOIN c.companyProperties p where c.id = :id")
.setParameter("id", companyId)
.getResultList();
Here the results will contain a single array of the selected fields. You can use getSingleResult, but be aware that it will throw an exception if no results were found.
I have a query
List<Integer> ids = sessionFactory.getCurrentSession()
.createSQLQuery("SELECT l.id FROM likes l INNER JOIN liketoanswers lta ON l.id = lta.id AND lta.answer_id = :a_id")
.setParameter("a_id",answer.getId())
.list();
List<Like> likes = new ArrayList<>();
for (Integer id : ids) {
likes.add(findById(id));
}
return likes;
I want to make this query like .createQuery("from Like l inner join fetch likes.answers la where la.id = answer.getId ..)
but word Like is registered in sql and a dont want to change entity class name.
I known that there a method to substitute class , but cannot find