I have 3 tables related with their FK and I trying to do a native query selecting entities joined. I did with 2 tables joined and it worked, but it does not work with 3.
This is my generic method for it
public List<Object[]> select3Tables(String sql, String parameter,
String tableAlias, String entityName, String tableAlias2, String path,
String tableAlias3, String path2){
Transaction tx = null;
List<Object[]>returnList = null;
try {
Query query = session.createNativeQuery(sql)
.addEntity(tableAlias, entityName)
.addJoin(tableAlias2, path)
.addJoin(tableAlias3, path2)
.setParameter("parameter", parameter);
returnList = query.getResultList();
tx.commit();
} catch (HibernateException e) {
if(tx!=null) tx.rollback();
System.err.println(e.getMessage());
e.printStackTrace();
}
and here is where I triying to do it.
public List<Compra> selectCompraByPropietario(final String dniPropitario) {
Compra compra = new Compra();
String sql = "SELECT * FROM Compras c "
+ "JOIN Montes m ON c.id_compra = m.compraFK_id_compra "
+ "JOIN Propietarios p ON m.propietarioFK_id_propietario = p.id_propietario"
+ "WHERE p.dni =:parameter";
List<Object[]> list = new HibernateSession().select3Tables(sql, dniPropitario, "compras",
"backend.entities.Compra", "m", "compras.montes", "m", "propietarios.montes");
for(Object[]listData : list) {
compra = (Compra) listData[0];
data.add(compra);
}
System.out.println("tamaño de data " + data.size());
return data;
}
Currently I´m getting an error "could not determine fetch owner : null"
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.HibernateException: Could not determine fetch owner : null
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1626)
at org.hibernate.query.Query.getResultList(Query.java:165)
at backend.HibernateSession.select3Tables(HibernateSession.java:149)
at backend.repositories.CompraOperations.selectCompraByPropietario(CompraOperations.java:90)
at backend.MainBackend.main(MainBackend.java:54)
Caused by: org.hibernate.HibernateException: Could not determine fetch owner : null
at org.hibernate.loader.custom.CustomLoader.determineAppropriateOwnerPersister(CustomLoader.java:292)
any idea what am I doing wrong and how to make it work?
Thank you.
I have faced quite similar problems like you
Everything seems fine to me.
Just add a space after
+ "JOIN Propietarios p ON m.propietarioFK_id_propietario = p.id_propietario"
Write it as
+ "JOIN Propietarios p ON m.propietarioFK_id_propietario = p.id_propietario "
Hope this helps
Related
I want to check if row record by id exists. I tried this:
public Optional<PaymentTransactions> transactionByUnique_Id( String unique_id ) throws Exception
{
String hql = "select e from " + PaymentTransactions.class.getName() + " e where e.unique_id = :unique_id";
TypedQuery<PaymentTransactions> query = entityManager.createQuery( hql, PaymentTransactions.class ) .setParameter( "unique_id", unique_id );
Optional<PaymentTransactions> paymentTransaction = query.getResultList().stream().findFirst();
return paymentTransaction;
}
Optional<PaymentTransactions> tnx = transactionsService.transactionByUnique_Id( transaction.getTransactionId() );
if(tnx.isPresent())
{
return "test";
// This method should be called only when DB record exists
}
But I alway get present object. What is the proper way to implement this check.
I tried to convert the List I got from Hibernate to AdminPopulate type using the following code, and I got this error
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to model.AdminPopulate
public class Test
{
public static void main(String[] args)
{
SubUser subUser=new SubUser();
List subUserList=subUser.getSubUserAll();
List<AdminPopulate> subUserListAdminPop=new ArrayList<AdminPopulate>();
for(Object p:subUserList)
{
subUserListAdminPop.add((AdminPopulate)p);
}
for(AdminPopulate p:subUserListAdminPop)
{
System.out.println("first ="+p.getFirstName());
}
}
}
....and this is the getSubUserAll() method
public List getSubUserAll()
{
Session session=null;
List resultsList=null;
try
{
CreateHibernateSession hbSession=new CreateHibernateSession();
session=hbSession.getHBSession();
String sql = "SELECT SubUser.FirstName,\n" +
"SubUser.LastName,\n" +
"SubUser.UserName,\n" +
"SubUserType.Name\n" +
"FROM SubUser\n" +
"INNER JOIN SubUserType ON SubUser.idSubUserType = SubUserType.idSubUserType\n" +
"WHERE SubUserType.idSubUserType != 0";
Query query = session.createSQLQuery(sql);
resultsList = query.list();
return resultsList;
}
catch(Exception ex)
{
ex.printStackTrace();
}
finally
{
session.close();
}
return resultsList;
}
If SubUser class is mapped properly to the result of the query, then you can just call query.addEntity(SubUser.class) prior to executing the query.
Query query = session.createSQLQuery(sql);
query.addEntity(SubUser.class);
resultsList = query.list();
I am not an expert in Hibernate, but you are trying to cast an array of objects (Object[] -> [Ljava.lang.Object;), what means, that the method Query.list has returned multiple results in a row. And if you look at your SQL, it is clear why, you are referencing two tables in the select.
I guess Query.list returned in every row an Object[2] with a SubUser in the first and a SubUserType in the second element.
How can i state the following mysql query in JPQL
select * from Price WHERE `valueDate` = (SELECT MAX(`valueDate`) FROM Price) and fundId = 2930
what i have tried is the following:
"select a from Price a where a.valueDate = select MAX(a.valueDate) and a.fund.id = :" +Price.QUERY_PARAM_FUND_ID
but get errors on that approach :
Caused by: <openjpa-2.3.0-r422266:1540826 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: "Encountered "MAX" at character 50, but expected: ["AND", "GROUP", "HAVING", "OR", "ORDER", <EOF>]." while parsing JPQL "select a from Price a where a.valueDate = select MAX(b.valueDate) from Price b and a.fund.id = :fundId"
I think it will work if you will added bracket before and after sub-query like.
"select a from Price a where a.valueDate = (select MAX(a.valueDate) from Price) and a.fund.id = :" +Price.QUERY_PARAM_FUND_ID
else let me say some thing related to hibernate implementation of JPA Specification.
If you have Hibernate model named 'Price' and you are going to do query through that model then. the HQL will be like that
try {
final StringBuilder qry = new StringBuilder();
qry.append(" SELECT")
.append(" FROM Price p")
.append(" WHERE p.valueDate = (SELECT MAX(pr.valueDate) FROM Price pr)")
.append(" AND p.fundId = :fundId");
return getJpaTemplate().execute(new JpaCallback() {
public Object doInJpa(EntityManager em)
throws PersistenceException {
Query q = em.createQuery(qry.toString());
q.setParameter("fundId", fundId);
return q.getResultList();
}
});
} catch (RuntimeException re) {}
I got a Login class:
if((!(name.equals(null) || name.equals("")) && !(password.equals(null) || password.equals(""))))
{
try{
loggedUser = checkLogin(name, hexPass.toString());
if(!loggedUser.isEmpty())
{
userdbId = loggedUser.get(0);
userdbName = loggedUser.get(1);
userdbPsw = loggedUser.get(2);
userdbType = loggedUser.get(3);
...
And a user DAO:
public List<String> checkLogin(String uname, String password) {
Session session = null;
List<String> lst = new ArrayList<String>();
try {
session = getSession();
String sql = "select * from user where uname='" + uname + "' and password='" + password + "'";
Query query = session.createSQLQuery(sql)
.addScalar("Id", StringType.INSTANCE)
.addScalar("uname", StringType.INSTANCE)
.addScalar("password", StringType.INSTANCE)
.addScalar("utype", StringType.INSTANCE);
lst = query.list();
}
catch (Exception e){
e.printStackTrace();
}
return lst;
}
The userdbId = loggedUser.get(0); generates error: 500
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to java.lang.String
com.se.pl.actions.LoginAction.execute(LoginAction.java:95)
I do not understand why this is happening since list of 4 strings is going to be put into 4 variables.
The error means that you have an Object and you are doing an implicit cast to String, so that's the error.
userdbId = loggedUser.get(0);
You can fix that by adding toString() method like:
userdbId = loggedUser.get(0).toString();
Of course, you are going to get the string representation for that object.
Note that if you have your own object you are going to get the following representation:
getClass().getName() + '#' + Integer.toHexString(hashCode())
In case you have this, you will need to override the toString() method in your class
You should use TypedQuery<T> instead of query and create objects of user entity type(if you have it defined - you definitely should have one) - it should look something like this (do not take this code literaly! I mainly use OpenJPA)
TypedQuery<UserEntity> query= session.createQuery("SELECT u FROM UserEntity u WHERE name=:name AND password=:password");
query.addParam("name",name);
query.addParam("password",password);
This probably should help:
Query query = session.createSQLQuery(sql)
.addScalar("Id", StringType.INSTANCE)
.addScalar("uname", StringType.INSTANCE)
.addScalar("password", StringType.INSTANCE)
.addScalar("utype", StringType.INSTANCE)
.setResultTransformer(org.hibernate.Criteria.ALIAS_TO_ENTITY_MAP);
Map row = (Map) query.uniqueResult();
lst.add((String) row.get("Id"));
lst.add((String) row.get("uname"));
lst.add((String) row.get("password"));
lst.add((String) row.get("utype"));
I have a field this is mounted in run-time, like a join of another fields. Look:
public String getNumeroCip() {
if (this.getId() == null) {
return "BR0000000000000";
}
String idFormated = String.format("%011d", this.getId());
return "BR" + idFormated + this.produto.getProduto().getSufixo();
}
This is my field, mounted in run-time. I can call it doing: bean.numeroCip.
But if i try use this in a HQL, like this:
#NamedQuery(name = "Ar.findByNumeroArOrCip", query = "SELECT c FROM AR c "
+ "JOIN FETCH c.produto "
+ "JOIN FETCH c.situacao "
+ "WHERE c.numeroAr = :numeroAr OR c.numeroCip = :numeroCip")
I got the following error when i try start tomcat server:
Caused by: org.hibernate.HibernateException: Errors in named queries: Ar.findByNumeroArOrCip
Transient fields cannot be used in HQL queries. In the end HQL query is translated to the SQL query, which is then executed against database. Database is not aware of fields of Java objects.