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

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

Related

Casting objects from Hibernate native multiple join query

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);

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!

How to write prepared statements for this query?

Hi i have written a join query for my app and its working. My next requirement is to convert that query to prepared statement where I am stuck.
"SELECT * FROM " + TableA.TABLE + " as d LEFT JOIN " + TableB.TABLE + " as c ON d."+ TableA.DAMAGECODE + "=c." + TableB.DAMAGECODE + " AND d."
+ TableA.INDEX + "=c." + TableB.DAMAGECODEINDEX + " AND d."
+ TableA.OBJECTTYPE + "=c." + TableB.OBJECTCLASS + " WHERE d."+ TableA.LEAF + " = '1' AND d." + TableA.OBJECTTYPE + " = ? AND " + "(d."+ TableA.DAMAGECODE + " LIKE ? OR d." + TableA.DAMAGETEXT + " LIKE ?) AND c." + TableB.CONSTRUCTIONSERIES + " = ? ORDER BY " + TableA.DAMAGETEXT;
cursor = db.rawQuery(sql,new String[]{String.valueOf(objectClass),"'%" + query + "%'","'%" + query + "%'",constructionSeries});
When i ran raw query i am getting results ,but when ran the above prepared statements i am getting cursor count always zero
You don't need to add the ' yourself when you pass a String parameters, the PreparedStatement will manage those itself.
"'%" + query + "%'"
For the moment you have condition like
where columnA = "'%somethingToFind%'"
So unless you have a value in columnA like 'somethingToFindInColumnA' (note the quote at the begin and the end of that String). You will never get a result.
Remove those to get something like :
"%" + query + "%"
Full answer :
db.rawQuery(sql,new String[]{String.valueOf(objectClass),"'%" + query + "%'","'%" + query + "%'",constructionSeries});
Become :
db.rawQuery(sql,new String[]{String.valueOf(objectClass),"%" + query + "%","%" + query + "%",constructionSeries});

Using SQlite to populate expandable list duplicating data into headers

I am trying to populate my expandable list from a SQLite DB, I got the expandable list tutorial from androidhive but it was for static data.
I got it working about 80% but now my problem is that the data gets populated under all the headers and not their unique headers. I think my problem is because all header and child data is using the same arrays and need to be unique to the headers?
What I was thinking was creating arrays dynamically with variable names but I have no idea how to do that and can't think of another way of doing this since this is my first time working with expandable lists.
Here is my code. I also have a feeling the way I am doing the nested cursors isn't the right way
String sqlQ = "SELECT Distinct "
+ "strftime('%d-%m-%Y', "+ SQLdb.DB_TIMEOPEN +") header " +
" FROM " + SQLdb.DICTIONARY_TABLE_NAME
+ " WHERE " + SQLdb.DB_PACKAGE + " = '"+ appPackage +"'"
+ " ORDER BY " + SQLdb.DB_TIMEOPEN + " ASC";
Cursor mCursor = dataBase.rawQuery(sqlQ, null);
Log.i("SQL",sqlQ);
if (mCursor.moveToFirst()) {
do {
listDataHeader.add(mCursor.getString(mCursor
.getColumnIndex("header")));
String sqlQ2 = "SELECT " + SQLdb.DB_NAME + ", "
+ SQLdb.DB_PACKAGE + ", "
+ SQLdb.DB_TIMEOPEN + ", "
+ SQLdb.DB_TIMECLOSED + ", "
+ SQLdb.DB_DURATION + ", "
+ "strftime('%d-%m-%Y', "+ SQLdb.DB_TIMEOPEN +") header " +
" FROM " + SQLdb.DICTIONARY_TABLE_NAME
+ " WHERE " + SQLdb.DB_PACKAGE + " = '"+ appPackage +"'"
+ " AND strftime('%d-%m-%Y', "+ SQLdb.DB_TIMEOPEN +") = '"+ mCursor.getString(mCursor
.getColumnIndex("header")) +"'"
+ " ORDER BY " + SQLdb.DB_TIMEOPEN + " ASC";
Cursor mCursor2 = dataBase.rawQuery(sqlQ2, null);
if (mCursor2.moveToFirst()) {
do {
listDataChildInner.add(mCursor2.getString(mCursor2
.getColumnIndex(SQLdb.DB_DURATION)));
listDataChildInnerO.add(mCursor2.getString(mCursor2
.getColumnIndex(SQLdb.DB_TIMEOPEN)));
listDataChildInnerC.add(mCursor2.getString(mCursor2
.getColumnIndex(SQLdb.DB_TIMECLOSED)));
Log.i("ACT CHILDT",mCursor.getString(mCursor
.getColumnIndex("header")) + " -> " + mCursor2.getString(mCursor2
.getColumnIndex(SQLdb.DB_TIMEOPEN)));
} while (mCursor2.moveToNext());
}
listDataChild.put(mCursor.getString(mCursor
.getColumnIndex("header")).toString(), listDataChildInner);
listDataChildO.put(mCursor.getString(mCursor
.getColumnIndex("header")).toString(), listDataChildInnerO);
listDataChildC.put(mCursor.getString(mCursor
.getColumnIndex("header")).toString(), listDataChildInnerC);
} while (mCursor.moveToNext());
}

Categories