how to map custom sql query to model to load on jsp view in spring - spring

I am beginner in spring. I want to show SQL data to JSP view page.
This is my SQL table
create table customer(
id int primary key,
name varchar(250),
salary int,
manager_id int
)
and I am trying to show data from this query
select m.id, m.name, m.salary, n.name from customer m, customer n where n.id=m.manager_id
So basically from this query, I am trying to show ID int, name varchar, salary int, manager_name varchar.
I have create the entity java class as below
#Entity
#Table(name="customer")
public class Customer{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column
private int id;
#Column
private String name;
#Column(name="manager_id")
private String manager;
#Column(name="salary")
private int salary;
............
............
}
This is the code of my DAO class
Session session= entityManager.unwrap(Session.class);
Query<Employee> query= session.createQuery(<above sql query need to add here?>,Customer.class);
return query.getResultList();
So the issues are,
This SQL query return the data which could not be matched to Customer Entity class. So do I need to create another Entity class for this? Is there any better way?
The above required SQL query is not able to execute. What the correct way to execute custom SQL query?

Regarding your first question: Yes there is better way. you can directly fetch the results in a projection dto class. take a at: https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/
About your second question: What Do you mean by saying the query does not execute?
Can you give us the Exception/Stacktrace? Did you try to execute the query (sql form of it) physically? Does it run then?

Related

Fetch specific columns dynamically

I have the following User entity:
public class User extends PanacheEntityBase{
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "DataIdGenerator")
#Column(name = "id")
public Long id;
public String name;
public String location;
public int age;
}
I also have the following endpoint: '/user', with a 'select' query parameter where you provide the column names you want to receive. It should be possible to select any combination of columns like: /user?select=id,name, /user?select=id,age, /user?select=name,age, /user?select=age,name
Based on the 'select' query I want to use a projection to get the selected columns only. Currently I'm using the query to create the following query fe: /user?select=id,name to SELECT d.id, d.name FROM User d, however I need the DTO to be dynamic based on the columns provided too.
Currently I have the following projection where UserDTO is a class with id and name attributes. This works fine, but if I change any parameter I need a different DTO.
// This variable is dynamically created based on query parameters
String query = 'SELECT d.id, d.name FROM User d'
return User.find(query).project(UserDTO.class).list();
Is it possible to make this projection DTO class more dynamic, so it supports all combinations?
I suspect the Panache API is not flexible enough at the moment to do what you are asking.
But you could use the Hibernate Reactive API without Panache:
#Inject
Mutiny.SessionFactory sf;
public Uni<List<Tuple>> find(String query) {
return sf.withSession(session ->
session.createQuery(query, Tuple.class).getResultList()
);
}
Once you have the Tuple, you can convert it to the type you prefer.

Join 2 tables using Spring JPA

I have two entities(Invoice and InvoiceItems) without adding any relationship.
Invoice
public class Invoice {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long invoiceID;
#Column(name="code")
private String code;
//other columns
}
Invoice Items
public class InvoiceItems {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long invItemID;
#Column(name="invoice_id")
private Integer invoiceId;
//other columns
}
Can I join these entities and get data without adding relationship using JPA?
If it isn't possible how to join 2 entities using JPQL or Native query?
If your data is valid then using native query you can do that
#Query(nativeQuery = true, "select * from Invoice i join InvoiceItems im on i.id = im.invoice_id")
public List<Invoice> findData();
But that is not a good way join without relation using JPA.
Yes, you can join these entities and get data without adding relationship using JPA, but it's a little bit losing the purpose of using JPA.
You need to create a java class first, which will be the returning data object from the DB. After that you can use entityManager's createNamedQuery method to get the result.
createNamedQuery(String sqlString, ResultClass.Class)
sqlString may be something like:
SELECT INV.INVOICE_ID
INV.CODE
INV_ITEMS.INV_ITEM_ID
FROM INVOICE INV
JOIN INVOICE_ITEMS INV_ITEMS
ON INV.INVOICE_ID = INV_ITEMS.INVOICE_ID;
And the corresponding ResultClass:
public class ResultClass {
private Long invoiceID;
private String code;
private Long invItemID;
// other columns
}
Or you can even use RowMapper to map the object all by yourself for more flexibility by using JdbcTemplate with query() method.

Select self referencing table with spring data into new object

I have a self referencing employee table. An Employee reports to his immediate lead which also an Employee.
fields->
id, name, employee_type, lead_id
I have mapped this table into this class,
public Class Employee {
private Integer id;
private String name;
private Integer employeeType; // 1-manager, 2-project lead, 3-developer, etc
private List<Employee> reporters;
}
How can I load all managers with his reporters using Spring Data JPA custom mapping? (those reporting employees will have their own reporters)
Mainly, I don't know how to map the corresponding list.
#Query("SELECT new Employee(id, name, employee_type) FROM employee")
List<Employee> findAllManagers();

HQL join query: Path expected for join

I'm new to hql, I referred to a site to write hql query in Spring Framework, but it throws "Path expected for join!" exception
My query is
"from GaugeCateSelect cs inner join PreferredUrl purl on cs.survey=purl.survey where purl.uuid=:uuid"
I want to connect both table with "survey".
How can I sort it out?
Update
Two tables, names are GaugeCateSelect and PreferredUrl. The "survey" field is common for both table. uuid is in PreferredUrl. I want to get all data from GaugeCateSelect when I pass the uuid to PreferredUrl table. (In short, Pass uuid to PreferredUrl, then find the survey number from PreferredUrl and check the number with GaugeCateSelect table, if exists get all data)
Update 2
There is no primary/foreign key reference relationship between two tables. but common field survey is there
GaugeCateSelect class
class GaugeCateSelect {
private int id;
private String categoryName;
private int posNeg;
private Survey survey; //survey is in foreign key relationship of survey table
//Annotation, getters and setters were removed for easiness.
}
PreferredUrl class
public class PreferredUrl {
private int preferredUrlId;
private String uuid;
private int enabled;
private Survey survey; //survey is in foreign key relationship of survey table
//Annotation, getters and setters were removed for easiness.
}
Maybe you should check the Hibernate version you use as there is a difference when joining unrelated entities as discussed here: https://www.thoughts-on-java.org/how-to-join-unrelated-entities/

Selecting from a view in H2 doesn't work

I recently replaced PostgreSql unit test database with an in memory H2 Database. I couldn't figure out why couple tests are failing, it was working fine with Postgre. There are approx. 280+ unit tests in this application. The failing dao tests are selecting from a view and the entity has a EmbeddedId, those the columns of that view.
See below code (Note: I changed names, code and the sql to hide the real names when writing this email, but this was a working unit test with Postgre db)
<pre>
#Table(name = "item_view") // <- item_view is a database view
public class ItemV implements Serializable
{
.....
#EmbeddedId // <- entity has an embedded id
private ItemVId id;
.....
#Embeddable
public static class ItemVId implements Serializable //<- This is the embeddedId
{
#Column(name = "item_id", updatable=false, insertable=false)
private Long ItemId; //<- col no.1 of view
#Column(name = "item_type_id", updatable=false, insertable=false)
private Integer ItemTypeId; //<- col no.2 of view
.....
ItemType is an enum
And the view is
CREATE OR REPLACE VIEW item_view AS
( ( ( SELECT pt.id as item_id, cit.id as item_type_id
FROM xyz pt, item_type cit
WHERE pt.name::text = 'xyz'::text
UNION
SELECT z.id as item_id, cit.id as item_type_id
FROM zzz z, item_type cit
WHERE z.name::text = 'zzz'::text)
..............
and the dao method is
public ItemView find(Long itemId, ItemType itemType)
{
String hql = " from ItemV iv where iv.id.itemId = :itemId and iv.id.itemTypeId = :itemTypeId ");
List<ItemView> result = (List<ItemView>)getEntityManager()
.createQuery(hql)
.setParameter("itemId", itemId)
.setParameter("itemTypeId", itemType.getId())
.setMaxResults(1)
.getResultList();
return result.isEmpty()
? null : result.get(0);
}
This dao method always returns empty results, never finding existing rows in the view??? I know those rows exist because when I do getAll() on the same dao I see results and I see a matching row for the criteria.
Is there anything special about selecting rows from a view in H2 database?
Thanks
Ok fixed, I had to use a smaller number for LOCK_TIMEOUT value, so now I can connect to database and see values. Selecting from view problem also fixed.
I have to say H2 is really neat and elegant. I'm glad, I switched the unit test db to H2.

Resources