Casting objects from Hibernate native multiple join query - java

I have a hibernate native sql query joining three tables, and I'm trying to retrive 3 columns from the result
public void doTestQuery() {
try (Session session = HibernateUtilities.getSessionFactory().openSession()) {
transaction = session.beginTransaction();
String sql = "SELECT\r\n"
+ " users.username, \r\n"
+ " user_roles.role_name, \r\n"
+ " address.address\r\n"
+ "FROM\r\n"
+ " address\r\n"
+ " INNER JOIN\r\n"
+ " users\r\n"
+ " ON \r\n"
+ " address.iduser = users.iduser\r\n"
+ " INNER JOIN\r\n"
+ " user_roles\r\n"
+ " ON \r\n"
+ " users.iduser = user_roles.iduser";
NativeQuery query = session.createNativeQuery(sql);
List<Object[]> results = query.list();
for (Object[] arr : results) {
System.out.println(arr[0].toString() +" "+ arr[1].toString() +" "+ arr[2].toString());
}
transaction.commit();
}
If I replace the System.out.println with this code below, it gives me an error. Is there a way to cast objects from this kind of hibernate queries?
Users user = (Users) arr[0];
UserRoles userRole = (UserRoles) arr[1];
Address _address = (Address) arr[2];
System.out.println(user.getUsername() + userRole.getRolename() + _address.getAddress());

Hibernate requires special aliases to be able to fetch the data from a result set. For this purpose, Hibernate supports a special template in native SQL.
String sql = "SELECT "
+ " {u.*},"
+ " {r.*},"
+ " {a.*} "
+ "FROM "
+ " address a "
+ " INNER JOIN "
+ " users u "
+ " ON a.iduser = u.iduser "
+ " INNER JOIN "
+ " user_roles r "
+ " ON u.iduser = r.iduser";
NativeQuery query = session.createNativeQuery(sql);
query.addEntity("u", Users.class);
query.addEntity("r", UserRoles.class);
query.addEntity("a", Address.class);

Related

SQL Query - FindCostumerWithHighestBill

I am try to find the costumer with the highest bill using this sql that I wrote , but apparently I run into this error :
Every derived table must have its own alias
This is what I wrote:
public static void findCustomerWithHighestBill(Connection c) throws SQLException {
String query = "SELECT CustomerID, CustomerName, CITY, sum(sum_all) As 'data'\r\n"
+ "FROM (SELECT *, sum(Price) As 'sum_all'\r\n"
+ " FROM (SELECT *, Customer.NAME AS \"CustomerName\"\r\n"
+ " FROM Transactions\r\n"
+ " INNER JOIN Product ON Product.ID = Transactions.ProductID\r\n"
+ " INNER JOIN Customer ON Customer.ID = Transactions.CustomerID)\r\n"
+ " GROUP BY CustomerID, ProductID\r\n"
+ " ) \r\n"
+ "GROUP BY CustomerID\r\n"
+ "ORDER BY data DESC";
Statement statement = c.createStatement();
ResultSet set = statement.executeQuery(query);
set.next();
System.out.println("CustomerID: " + set.getInt("CustomerID") +
", Name: " + set.getString("CustomerName") + ", City: " +
set.getString("CITY") + ", Bill: " + set.getFloat("data"));
}
Can please somoane help me zith this ?
Coming back ,
It seems that indeed ad most of you says in the comments I should identify my tables first but, apparently I also have miss to avoid the duplicate ID column.
Here goes my new query:
String query = "SELECT CID, CustomerName, City, sum(sum_all) As data" +
" FROM (SELECT *, sum(PPROD) As sum_all" +
" FROM (SELECT Product.ID as PID,Customer.ID as CID,Product.Price as PPROD,City, Customer.NAME AS CustomerName" +
" FROM Transactions" +
" INNER JOIN Product ON Product.ID = Transactions.ProductID" +
" INNER JOIN Customer ON Customer.ID = Transactions.CustomerID) As t2" +
" GROUP BY CID, PID" +
" ) As t1" +
" GROUP BY CID" +
" ORDER BY data DESC;";

Pass Nullable values using Preparement state

I have this query, and I would like to pass the null value. How to do this using Preparement state
The column that must be null is E.RTCA_CD_QMNUM IN (:1)
String sqlSigiop = "SELECT E.RTCA_CD_QMNUM"
+ ", E.RTIT_NR_ITEM"
+ ", D.RTSI_NR_SUBITEM"
+ ", B.PLOP_DT_INICIO"
+ ", B.PLOP_DT_FECHAMENTO"
+ ", D.RTSI_DT_MAIS_CEDO"
+ ", A.SSRT_CD_STATUS_SUBITEM_RT"
+ ", D.RTSI_DT_MAIS_TARDE"
+ ", A.PORT_DT_INCLUSAO"
+ ", C.PLCO_DS_PLANEJ_CONFIG"
+ ", F.ROTA_NM_ROTA"
+ ", H.CLLO_NM_CLUSTER_LOG"
+ ", G.ATEM_DT_INICIO"
+ ", I.TIAM_DS_TIPO_ATEND_MAR "
+ "FROM SIGIOP.PLANEJAMENTO_OPERACIONAL_RT A "
+ "INNER JOIN SIGIOP.PLANEJAMENTO_OPERACIONAL B ON B.PLOP_SQ_PLANEJ_OPER = A.PLOP_SQ_PLANEJ_OPER "
+ "INNER JOIN SIGIOP.PLANEJAMENTO_CONFIG C ON C.PLCO_SQ_PLANEJ_CONFIG = B.PLCO_SQ_PLANEJ_CONFIG "
+ "INNER JOIN SIGIOP.RT_SUBITEM D ON D.RTSI_CD_RTSUBITEM = A.RTSI_CD_RTSUBITEM "
+ "INNER JOIN SIGIOP.RT_ITEM E ON E.RTIT_CD_RTITEM = D.RTIT_CD_RTITEM "
+ "INNER JOIN SIGIOP.ROTA F ON F.ROTA_SQ_ROTA = A.ROTA_SQ_ROTA "
+ "INNER JOIN SIGIOP.ATENDIMENTO_MAR G ON G.ATEM_SQ_ATEND_MAR = A.ATEM_SQ_ATEND_MAR "
+ "INNER JOIN SIGIOP.CLUSTER_LOG H ON H.CLLO_SQ_CLUSTER_LOG = G.CLLO_SQ_CLUSTER_LOG "
+ "INNER JOIN SIGIOP.TIPO_ATENDIMENTO_MAR I ON I.TIAM_SQ_TIPO_ATEND_MAR = G.TIAM_SQ_TIPO_ATEND_MAR "
+ "WHERE (B.PLOP_DT_FECHAMENTO >= TO_DATE('"+dataInicio+"', 'DDMMYYYY') OR B.PLOP_DT_FECHAMENTO IS NULL)"
+ "AND (B.PLOP_DT_FECHAMENTO < TO_DATE('"+dataFim+"', 'DDMMYYYY') OR B.PLOP_DT_FECHAMENTO IS NULL) "
+ "AND A.MORE_SQ_MOTIVO_REPLANEJ IS NULL "
+ "AND B.PLOP_IN_STATUS = 2 "
+ "AND E.RTCA_CD_QMNUM IN (:1) "
+ "ORDER BY E.RTCA_CD_QMNUM, E.RTIT_NR_ITEM, D.RTSI_NR_SUBITEM, B.PLOP_DT_INICIO";
/
Statement stSigiop = cnnSigiop.createStatement();
ResultSet resultSigiop = stSigiop.executeQuery(sqlSigiop.replace(nullable ":1", rts.toString().replace("[", "").replace("]", "")));
while (resultSigiop.next()) {TO DO}
you have to change your query to this :
...
+ "AND (E.RTCA_CD_QMNUM IS NULL OR E.RTCA_CD_QMNUM IN (:1)) "
...

UNION in Spring data JPA native query two table

I have a requirement where i need to fetch number of record both the table using JPA native UNION query for Pagination
table 1=>txrh_bcaterms
table 2=> txrm_bcaterms
Ex: txrh_bcaterms UNION txrm_bcaterms
In Below code i am trying to fetching the record in both table Using UNION
#Query(nativeQuery = true,value= "SELECT "
+ " customerid, "
+ "finance_type, "
----------
-------etc----
+ "institution, "
+ "limit_groupid, "
+ "tx_booking_location, "
+ "finance_tenor_days, "
+ "margin_type , "
+ "additional_margin_percentage, "
+ "margin_percentage, "
+ "stale_document_condition_proforma_fin, "
+ "customer_name "
+ "from "
+ "txrh_bcaterms "
+ "where "
+ " institution=:institution "
+ "AND tx_booking_location=:txBookingLocation "
+ "OR finance_type=:financeType "
+ "OR customerid=:customerID "
+ "OR limit_groupid=:limitGroupID "
+ "UNION "
+ "SELECT "
+ "customerid, "
+ "finance_type, "
----------
-------etc----
+ "institution, "
+ "limit_groupid, "
+ "tx_booking_location, "
+" finance_tenor_days, "
+ "margin_type, "
+ "additional_margin_percentage, "
+ "margin_percentage, "
+ "stale_document_condition_proforma_fin, "
+ "customer_name "
+ "from txrm_bcaterms "
"
+ " institution=:institution "
+ "AND tx_booking_location=:txBookingLocation "
+ "OR finance_type=:financeType "
+ "OR customerid=:customerID "
+ "OR limit_groupid=:limitGroupID "
)
Page<Map<String,Object>> historyAndMaster(#Param("institution") String institution, #Param("txBookingLocation") String txBookingLocation,
#Param("financeType") String financeType, #Param("customerID") String customerID, #Param("limitGroupID") String limitGroupID, Pageable page);
NOTE:Actually stepid is the primary key txrh_bcaterms table and stepid is not there txrm_bcaterms table
ERROR
-------
in ui i passed institution =BC/AC/EC then UNION query able to execute and getting data
but if i passed SC then getting below exception
Caused by ERROR: each UNION query must have the same number of columns
Position: 581
at org.axonframework.axonserver.connector.ErrorCode.lambda$static$15(ErrorCode.java:107)
... 9 common frames omitted
=>If there is no same number of columns then how it is worked BC/AC/EC
I am new the Spring Data JPA Could you please help me to resolve this issue
Any other better suggestion welcome!

Hibernate/JPA map Result of native Query to non-Entity holding Entities

I do have 3 Entities and want to Cross-Join them. As I do not need to create a new Entity for this I just wanted to map the by fetching with a native Query:
EntityA{
...
String someValue;
}
EntityB{
...
String someValue;
}
EntityC{
...
String someValue;
}
And the CrossJoined Object
CrossJoinedFoo{
EntityA entityA;
EntityB entityB;
EntityC entityC;
}
I am using it like:
private static final String _SELECT_CROSS_JOIN_ENTITIES = "SELECT * FROM "
+ "EntityA"
+ ", "
+ "EntityB"
+ ", "
+ "EntityC"
+ " WHERE (1=1) "
+ " AND " + "EntityA.someValue = :someValue"
+ " AND " + "EntityB.someValue = :someValue"
+ " AND " + "EntityC.someValue = :someValue";
Query query = entityManager.createNativeQuery(_SELECT_CROSS_JOIN_ENTITIES);
query.setParameter(":someValue", "foo");
How can I achieve this behavior?
You can go for a HQL query and use the result class strategy.
Just remember to add a constructor to CrossJoinedFoo accepting 3 entities in appropriate order:
private static final String _SELECT_CROSS_JOIN_ENTITIES =
"SELECT new my.package.CrossJoinedFoo(a,b,c) FROM "
+ "EntityA a"
+ ", "
+ "EntityB b"
+ ", "
+ "EntityC c"
+ " WHERE (1=1) "
+ " AND " + "a.someValue = :someValue"
+ " AND " + "b.someValue = :someValue"
+ " AND " + "c.someValue = :someValue";
Query query = entityManager.createQuery(_SELECT_CROSS_JOIN_ENTITIES);
query.setParameter(":someValue", "foo");
List<CrossJoinedFoo> result = query.list();
Just remember to change the package to an appropriate one.
Using #SqlResultSetMapping with #ConstructorResult
Beware that the resulted entities won't be managed

JAVA Persistance OrderBy before a GroupBy

we need to get the last post message group by a transmitter.
Query query = em.createQuery("SELECT m FROM Message m " +
"JOIN m.transmitter " +
"JOIN m.recipient " +
"WHERE m.transmitter = :u1 " +
"OR m.recipient = :u1 " +
"GROUP BY m.recipient,m.transmitter " +
"ORDER BY m.sendDate DESC");
query.setParameter("u1", actualUser);
but we need something like this where we get the oldest message:
Query query = em.createQuery("SELECT m FROM Message m " +
"JOIN m.transmitter " +
"JOIN m.recipient " +
"WHERE m.transmitter = :u1 " +
"OR m.recipient = :u1 " +
"ORDER BY m.sendDate DESC"
"GROUP BY m.recipient,m.transmitter ");
query.setParameter("u1", actualUser);
Thanks for help sorry for my English.
My solution is to get all contact first and then get the last send message from a contact (two queries instead of one big.
Maybe like this?
Query query = em.createQuery("SELECT m FROM Message m " +
"WHERE m.sendDate = (" +
"SELECT MAX(m.sendDate) FROM MESSAGE m "
"JOIN m.transmitter t " +
"JOIN m.recipient r " +
"WHERE t = :u1 " +
"OR r = :u1)");
query.setParameter("u1", actualUser);

Categories