how to map native sql query to Entity - java

lets say I have the following Entities
#Entity
public class Person{
private int id;
private String firstName;
private String lastName;
#OneToOne
private B b;
...
}
#Entity
public class B{
private int id;
private String x;
private String y;
...
}
What I want to do is create a SELECT query from a join that returns columns from multiple tables. From the resultset I want to create Objects of Entity Person, process them and then persist them. Something like this
List<Person> list = entityManager.createNativeQuery("SELECT p.firstName, p.lastName, st.entityB FROM someTable st JOIN Person p ON p.lastName = st.lastName").getResultList()
In the statement "someTable" is an unmanaged class, so there is no Entity class for that but it has a column with a reference to the Entity B.
This statement doesnt work but in my current solution I am just returning List<Object[]>. From there I could create a Person but would need to resolve the B Entity because I only get scalar types. Is there a cleaner way somehow, so that I could directly get a List of type Person and also the B Entity is resolved?

Related

Spring Data Projection with OneToMany returns too many results

I have a JPA entity (Person) with onetomany relation (ContactInfo).
#Entity
public class Person {
#Id
#GeneratedValue
private Integer id;
private String name;
private String lastname;
private String sshKey;
#OneToMany(mappedBy = "personId")
private List<ContactInfo> contactInfoList;
}
#Entity
public class ContactInfo {
#Id
#GeneratedValue
private Integer id;
private Integer personId;
private String description;
}
I've defined a projection interface that includes this onetomany relation as described here.
public interface PersonProjection {
Integer getId();
String getName();
String getLastname();
List<ContactInfo> getContactInfoList();
}
public interface PersonRepository extends JpaRepository<Person,Integer> {
List<PersonProjection> findAllProjectedBy();
}
When I retrieve the data with findAllProjectedBy the result contains too many rows. It looks like the returned data is the result of a join query similar to:
select p.id, p.name, p.lastname, ci.id, ci.person_id, ci.description
from person p
join contact_info ci on ci.person_id = p.id
For example for this data set:
insert into person (id,name,lastname,ssh_key) values (1,'John','Wayne','SSH:KEY');
insert into contact_info (id, person_id, description) values (1,1,'+1 123 123 123'), (2,1,'john.wayne#west.com');
The findAllProjectedBy method returns 2 objects (incorrectly) and the standard findAll returns 1 object (correctly).
Full project is here
I've done some debugging and it seems that the problem is with the jpa query.
The findAll method uses this query:
select generatedAlias0 from Person as generatedAlias0
The findAllProjectedBy uses this query:
select contactInfoList, generatedAlias0.id, generatedAlias0.name, generatedAlias0.lastname from Person as generatedAlias0
left join generatedAlias0.contactInfoList as contactInfoList
Does anyone know how to fix this invalid behaviour?
A quick fix for this problem is described here:
https://jira.spring.io/browse/DATAJPA-1173
You need to describe one of the single projection attributes with a #Value annotation. For the example posted above you will end up with:
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
public interface PersonProjection {
#Value("#{target.id}")
Integer getId();
String getName();
String getLastname();
List<ContactInfo> getContactInfoList();
}

JPQL - How can I get an extra param inside my entity?

I am new to JPQL and I am trying to get an extra parameter that is not in the entity, but I am not finding how to do it.
Through searched here in the forum I found out that some uses a DTO for it, but I am not knowing how to apply that.
Here is my entity:
#Entity
#Table(name = "person")
public class Person implements Serializable {
private int id;
private String name;
private String email;
private int age;
...
}
And my JPQL:
SELECT COUNT(a.name) as countOfNames, a FROM Person a WHERE a.name like :name
How can I get the countOfNames result inside of myentity object since it is not a column?
The simplest way is to use a constructor expression
package com.entites
public class PersonDto {
private Person person;
private Integer countOfNames;
public PersonDto(Person person, Integer countOfNames) {
this.person = person;
this.countOfNames = countOfNames;
}
}
select new com.entites.PesronDto(a, count(a.name))
from Person a
where a.name like :name

Spring data JPA - Exclude ID column from one entity parameter

I have two entities :
#Entity
public class Car {
#Id
private Long id;
#OneToOne
private Engine engine;
}
and the other one :
#Entity
public class Engine {
#Id
private Long id;
#Column
private String value1;
#Column
private String value2;
}
In my jpaRepositoy interface, i would like to do :
public interface CarRepository extends JpaRepository<Car, Long> {
public Car findByEngine(Engine engine);
}
But this method doesn't return my entity stored, because I created my Engine doing :
Engine engine = new Engine("someValue", "someValue");
without setting engine's id which is stored in database.
So I would like to know if it is possible exclude a column like id ?
If no, is the only way to do this is :
#Query("SELECT c FROM Car c WHERE c.engine.value1 = :value1 and c.engine.value2 = :value2")
findByEngine(#Param("value1") String value1, #Param("value2") String value2)
?
Related question : If I have OneToMany relationship instead of OneToOne, like
#Entity
public class Car {
#Id
private Long id;
#OneToMany
private List<Engine> engines;
}
How can I do this request to have something like (still without id column) :
public Car findByEngines(List<Engine> engines);
Thanks a lot !
This #Query("SELECT c FROM Car c WHERE c.value1 = :value1 and c.value2 = :value2") is not correct jpql query for your scenario, You do not have value1 and value2 in Car entity.
Correct one would be:
#Query("SELECT c FROM Car c WHERE c.engine.value1 = :value1 and c.engine.value2 = :value2").
You can try this method Name, I think that will work:
findByEngineValue1AndEngineValue2(String value1, String value2)
but for list one, i do not think you can make it up with just method name.

How Join hibernate Value objects using HQL query?

Hi i'm New to write HQL Query please help me.....
my Hibernate have three ValueObjects ie.
#Entity
#Table(name="user")
public class UserVO {
#Id
#Column(name="S_ID")
private String s_id;
#Column(name="FIRSTNAME")
private String firstName;
private String email;
}
CourseVO class
#Entity
#Table(name="course")
public class CourseVO
{
#Id
#Column(name="S_ID")
public String s_id;
#Column(name="NAME")
public String name;
}
Skillset VO
#Entity
#Table(name="skillset")
public class SkillsetVO
{
#Id
#Column(name="S_ID")
public String s_id;
#Column(name="COURSE_ID")//Foreign Key "USER"
public String course_id;
#Column(name="USER_ID")//Foreign key "COURSE"
public String user_id;
#Column(name="TEACH_EXP")
public String teach_Exp;
}
Now How to get Values of FirstName,NAME,TEACH_EXP values using EMAIL of USER table using HQL query
If you want to use join syntax in HQL you must work out your mapping accordingly as joins are enabled by mapping.
#Entity class A { #OneToMany private List<B> bs; }
#Entity class B { #Basic int n; }
Enables
select b from A a inner join a.b where a = :id
But with your mapping this is not possible. Also bear in mind that in terms of efficiency most of the RDBMs will perform an inner join on a where a.id = b.id.
select u.firstName, c.name, s.teach_Exp
from UserVO u, CourseVO c, SkillsetVO s
where
u.s_id = s.user_id
and c.s_id = s.course_id
and u.email = :email
But I think that you must review you association. Since looks to me that SkillsetVO.user_id should be SkillsetVO.User (an association to a UserVO entity and same for CourseVO).

Hibernate query on superclass property

First of all, please forgive my ignorance in both Java and Hibernate, I'm studying different ORM solutions and am not a Java programmer.
1) Is it possible to map the following class hierarchy to a database table, with Person.name and Employee.name pointing to different columns?
abstract public class Person {
private String name;
}
public class Employee extends Person {
private String name;
}
2) Supposing that the answer to 1) is Yes, is there a way to create a HQL or Criteria query which would ask Hibernate to return Employee objects, with a criterion on Person.name?
Something like that:
SELECT e FROM Employee e WHERE e.super.name = "test";
1) Yes. This can be accomplished via a MappedSuperclass, and annotating your columns
#MappedSuperclass
abstract public class Person {
#Column(name="PERSON_NAME")
private String name;
}
#Entity
public class Employee extends Person {
#Column(name="EMPLOYEE_NAME")
private String name;
}
2) No. Not without changing the attribute names of one of either Person or Employee. You could however query for all person objects with that name and cast the results to Employees. Another option would be to use Native SQL to query the column you want, again probably not ideal.
SELECT p FROM Person p WHERE p.name = "test";

Categories