When I try to run this query with hibernate in Java somethings go wrong and throws an error like
( 12002 ) Internal Service Error. Exception Message : Bad Sql Grammar Exception occurred [Hibernate operation: could not execute query; bad SQL grammar [SELECT COMDT_COM_STAT, COMDT_COM_REFNO, COMDT_COM_CCY
FROM COMDT
WHERE COMDT_COM_REFNO = ?
AND COMDT_COM_RDN BETWEEN ? AND ?
AND COMDT_COM_STAT = ?
GROUP BY COMDT_COM_STAT, COMDT_COM_REFNO, COMDT_COM_CCY
ORDER BY COMDT_COM_REFNO]; nested exception is java.sql.SQLException: Invalid Column Name]
But when I run the same query with proper inputs in PLSQL, everything works as I expected. I am working on this error for 2 days but nothing came up.
Thanks.
QUERY
<sql-query name="getCommissionBetweenDatesWithStat">
<return alias="xyz"
class="com.ykb.hmn.cms.commission.datamodel.IComDetail"/>
<![CDATA[
SELECT COMDT_COM_CCY AS {xyz.currency}, SUM(xyz.COMDT_COM_AMT1) AS {xyz.amount1}
FROM COMDT
WHERE COMDT_COM_REFNO = :refNo
AND COMDT_COM_RDN BETWEEN :startRdn AND :endRdn
AND COMDT_COM_STAT = :stat
GROUP BY COMDT_COM_STAT, COMDT_COM_REFNO, COMDT_COM_CCY
ORDER BY COMDT_COM_REFNO
]]>
</sql-query>
Entity
<class name="com.ykb.hmn.cms.commission.datamodel.IComDetail"
table="COMDT">
<tuplizer class="com.ykb.hmn.inf.core.datamodel.IntfEntityTuplizer"
entity-mode="pojo" />
<id name="oid" type="java.lang.Long">
<column length="17" name="COMDT_ID" />
</id>
<property name="refNo" type="long">
<column length="12" name="COMDT_COM_REFNO" />
</property>
<property name="stat" type="string">
<column length="1" name="COMDT_COM_STAT" />
</property>
<property name="relDay" type="int">
<column length="5" name="COMDT_COM_RDN" />
</property>
<property name="amount1" type="big_decimal">
<column precision="18" scale="2" name="COMDT_COM_AMT1" />
</property>
<property name="currency" type="string">
<column length="4" name="COMDT_COM_CCY" />
</property>
<class/>
Table Schema
COMDT_ID NUMBER(17)
COMDT_COM_REFNO NUMBER(12)
COMDT_COM_AMT1 NUMBER(18,2)
COMDT_COM_STAT VARCHAR2(1)
COMDT_COM_RDN NUMBER(5)
COMDT_COM_CCY VARCHAR2(4)
Thanks.
My guess, hibernate named query should be declared using the property name, not the column name. So instead of using column name in the named query, use the property name.
See this example for more details:
https://www.journaldev.com/3451/hibernate-named-query-example-namedquery
Related
My application contains both ORM and OGM. For ORM I was wrote some named queries in xyz.hbm.xml. But while using OGM those queries caused for exception. I am using OGM 4.1.3.Final version. Please help someone.
example.hbm.xml
<?xml version="1.0" ?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Jan 1, 2015 1:53:57 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="mkcl.os.apps.edumiss.model.student.Admission" table="ADMISSION">
<id name="id" type="java.lang.String">
<column name="ADMISSION_ID" />
<generator class="uuid" />
</id>
<property name="studentId">
<column name="STUDENTID" />
</property>
<property name="schoolId">
<column name="SCHOOL_ID" />
</property>
<property name="academicYearId" type="int">
<column name="ACADEMICYEARID" />
</property>
<property name="sectionRollNumber" type="int">
<column name="SECTIONROLLNUMBER" />
</property>
<property name="admissionDate" type="java.util.Date">
<column name="ADMISSIONDATE" />
</property>
<property name="schoolLeavingDate" type="java.util.Date">
<column name="SCHOOL_LEAVING_DATE" />
</property>
<property name="standardId" type="short">
<column name="STANDARDID" />
</property>
<property name="standardName" type="java.lang.String">
<column name="STANDARD_NAME" />
</property>
<property name="sectionId">
<column name="SECTION_ID" />
</property>
<property name="sectionName">
<column name="SECTION_NAME" />
</property>
<property name="reasonForLeaving">
<column name="REASON_FOR_LEAVING" />
</property>
<property name="streamId" type="short">
<column name="STREAM_ID" />
</property>
<property name="streamName" type="java.lang.String">
<column name="STREAM_NAME" />
</property>
<property name="admissionType" column="ADMISSION_TYPE">
<type name="org.hibernate.type.EnumType">
<param name="useNamed"></param>
<param name="enumClass">mkcl.os.apps.edumiss.model.student.AdmissionType</param>
</type>
</property>
<property name="createdBy" type="java.lang.String">
<column name="CREATED_BY" />
</property>
<property name="createOn" type="java.util.Date">
<column name="CREATED_ON" />
</property>
<property name="modifiedBy" type="java.lang.String">
<column name="MODIFIED_BY" />
</property>
<property name="lastModified" type="java.util.Date">
<column name="LAST_MODIFIED" />
</property>
<property name="patternId" type="integer">
<column name="PATTERN_ID"></column>
</property>
</class>
<sql-query name="getAdmissionForAcademicYear">
<return alias="admission" class="mkcl.os.apps.edumiss.model.student.Admission"></return>
<![CDATA[
SELECT
{admission.*}
FROM
ADMISSION admission
INNER JOIN STUDENT s
ON
s.CURRENT_ADMISSION_ID = admission.ADMISSION_ID
WHERE
admission.STUDENTID = :mkclIdentificationNumber
AND
admission.ACADEMICYEARID = :academicYearId
]]>
</sql-query>
</hibernate-mapping>
this throws
java.lang.IncompatibleClassChangeError: class org.objectweb.asm.tree.ClassNode has interface org.objectweb.asm.ClassVisitor as super class
if I am removing above query from hbm file then it worked fine. But I have to keep those queries in .hbm.xml file as it is.
That query is for a relational database, so you don't need the OGM for that.
Why do you want to run an SQL query against OGM, which is for NoSQL?
The default hibernate.archive.autodetection property value is class,hbm, so make sure you set it to class in the persistence.xml file that's associated to the OGM EntityManagerFactory. You do have two separate persistence.xml configurations (one for ORM and one for OGM), right?
according to current version of OGM(5.0) feature document:
Model can not possible to share between OGM and ORM together and this will projected to resolve in next version of OGM.
ORM classes can try to parse the .hbm.xml file and find the named queries which having the syntax of mongo query. so while reading the file OGM unable to parse the syntax of SQL named query and throws an error so I have only way to shift the all the queries into another hbm whose wntry will not be present in nosql_hibernate.xml file so OGM will not parse and my code will run fast else till this feature not support shift to another framework.
I am getting following exception while calling a main method.
I am posting mapping file here.
I think this is due to
<list-index>
<column name="bill_no" />
</list-index>
What should be value for this
<hibernate-mapping>
<class name="iland.hbm.BillDetails" table="bill_details" catalog="retail_shop">
<id name="billNo" type="java.lang.Long">
<column name="bill_no" />
<generator class="identity"></generator>
</id>
<many-to-one name="customerDetails" class="iland.hbm.CustomerDetails" fetch="join">
<column name="customer_id" not-null="true" />
</many-to-one>
<property name="subTotal" type="java.lang.Float">
<column name="sub_total" precision="10" />
</property>
<list name="billProductDetailses" table="bill_product_details" inverse="true" lazy="false" fetch="join">
<key>
<column name="bill_no" not-null="true" />
</key>
<list-index>
<column name="bill_no" />
</list-index>
<one-to-many class="iland.hbm.BillProductDetails" />
</list>
</class>
</hibernate-mapping>
Error:
Initial SessionFactory creation failed.org.hibernate.MappingException: Repeated column in mapping for collection: iland.hbm.BillDetails.billProductDetailses column: bill_no
Exception in thread "main" java.lang.ExceptionInInitializerError
at iland.database.HibernateUtil.<clinit>(HibernateUtil.java:32)
at iland.bill.BillDAO.fetchAll(BillDAO.java:94)
Caused by: org.hibernate.MappingException: Repeated column in mapping for collection: iland.hbm.BillDetails.billProductDetailses column: bill_no
at org.hibernate.mapping.Collection.checkColumnDuplication(Collection.java:341)
at org.hibernate.mapping.Collection.checkColumnDuplication(Collection.java:354)
How to resolve above error.
Indeed you are mapping twice the same column in your entity.
<list name="billProductDetailses" table="bill_product_details" inverse="true" lazy="false" fetch="join">
<key>
<column name="bill_no" not-null="true" />
</key>
<list-index>
<column name="bill_no" />
</list-index>
<one-to-many class="iland.hbm.BillProductDetails" />
</list>
When you map twice the same column (bill_product_details.bill_no) in an entity (suppose the properties A and B of your object reference the same column), Hibernate produces that exception because it doesn't know when to update/insert the datum on the db (when A is changed or when B is changed? And what if A and B are different?), so you have to tell it which one is the "master", let's say.
In addition, let me point out that I don't understand your mapping. The "key" should map to the column with the foreign key constraint, while the index should map the column indicating what will be the object's position in your list/array, so I really don't get why they both reference the same column. This way the position of the object in the array will be equal to the id of the referenced entry. Won't it?
I am developing a database connector in order to retrieve data from a Oracle database. I have used the Hibernate tool included as a plug-in in Eclipse for the generation of the Hibernate mapping files because I have a lot of classes and tables to map. However, when I run the application, I have just get the following Exception:
java.lang.ClassCastException: org.hibernate.type.StringType cannot be cast to org.hibernate.type.VersionType
at org.hibernate.tuple.PropertyFactory.buildVersionProperty(PropertyFactory.java:107)
at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:181)
at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:485)
at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:133)
at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:84)
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:286)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1845)
at eu.cartif.dwhconn.database.DBManager.checkDWHStatus(DBManager.java:57)
at eu.cartif.dwhconn.database.DBManager.main(DBManager.java:24)
I think the problem could be the type of the property of the hbm file:
<hibernate-mapping>
<class name="eu.cartif.dwhconn.database.Ifcactorrole" table="IFCACTORROLE">
<id name="role" type="string">
<column name="ROLE" length="50" />
<generator class="assigned" />
</id>
<property name="userdefinedrole" type="string">
<column name="USERDEFINEDROLE" />
</property>
<property name="description" type="string">
<column name="DESCRIPTION" length="3000" />
</property>
<set name="ifcpersons" table="IFCPERSON" inverse="true" lazy="true" fetch="select">
<key>
<column name="ROLES" length="50" />
</key>
<one-to-many class="eu.cartif.dwhconn.database.Ifcperson" />
</set>
<set name="ifcpersonandorganizations" table="IFCPERSONANDORGANIZATION" inverse="true" lazy="true" fetch="select">
<key>
<column name="ROLES" length="50" />
</key>
<one-to-many class="eu.cartif.dwhconn.database.Ifcpersonandorganization" />
</set>
</class>
</hibernate-mapping>
However, I am not sure about it and I would not like to change all the types in all the hbms if that is not the solution. Anyone could help me, please.
Thank you very much in advance,
May you have a nice day
In my case, I generated entity from DB and some entities column name has "version". Generator for this names add "#Version" annotation, but this column type is String - for #Version annotation unacceptable
This types of problem occurs
if there are column name as "version" of "VARCHAR" (string) type in any table, means in hibernate "property" becomes "version" and "type" becomes "string", like-
in .hbm.xml file
<version name="xyz" type="string">
<column name="xyz" length="30" not-null="true" />
</version>
if there are any missing getter or setter method for a particular attribute.
if there are mismatch between .hbm.xml file and POJO class file.
I have checked several times all the mapping classes. Finally, the problem came from a mapping class which had not the proper type for an attribute... :(
Thank you for your responses
Missing length field on
<property name="userdefinedrole" type="string">
<column name="USERDEFINEDROLE" />
</property>
I faced this problem with working on an ancient, hibernate3 software.
The solution is this: until hibernate3.5, StringType was a child class of NullableType.
In hibernate 3.6, this relation was ended.
Thus, StringType was convertable to a NullableType only until hibernate 3.5, from hibernate 3.6 it is not so any more.
The simplest solution is, now decades away from the future: switch back to hibernate 3.5.
My Hibernate hbm file looks something like this with a mysql DB:
<hibernate-mapping>
<class name="com.company.common.bo.position.Parent" table="Parents"
abstract="true">
<id name="id">
<generator class="increment" />
</id>
<property name="date" not-null="true" />
<property name="milliseconds" not-null="true" />
<property name="shares">
<column name="shares" precision="19" scale="6" not-null="true" />
</property>
<many-to-one name="ticker" column="tickerID" not-null="true" index="_tickerID_date_milliseconds_idx" />
<many-to-one name="auditTrail" column="auditTrailID"
not-null="false" cascade="save-update" lazy="false" fetch="select" />
<union-subclass name="com.company.common.bo.position.SubclassA"
table="SubclassAs">
<many-to-one name="account" column="accountID" not-null="true" foreign-key="SubclassA_accountID_fk" />
<many-to-one name="portfolio">
<column name="portfolioID" not-null="true"/>
</many-to-one>
<many-to-one name="individualTrade">
<column name="individualTradeID" not-null="false"/>
</many-to-one>
<many-to-one name="positionTransfer" column="positionTransferID"
cascade="save-update" not-null="false"/>
</union-subclass>
<union-subclass
name="com.company.common.bo.position.SubclassB" table="SubclassBs">
<many-to-one name="individualTrade">
<column name="individualTradeID" not-null="false" />
</many-to-one>
<many-to-one name="account" column="accountID" not-null="true" foreign-key="SubclassBs_accountID_fk"/>
<many-to-one name="internalExecution" column="executionID"
cascade="save-update" not-null="false" />
</union-subclass>
<union-subclass name="com.company.common.bo.position.SubclassC"
table="SubclassCs">
</union-subclass>
</class>
So basically i have an abstract class Parent and 3 subclasses (SubclassA, B, C) that extend it. In the database there are 3 tables (for the 3 subclasses). The id generator is "increment" because the union subclass mapping doesn't allow me to use native. So it looks like with increment, the ID is unique among the 3 tables. When I look at the hibernate sql, it basically finds the max ID from all 3 tables, and uses that as the next ID. But the query it uses seems very inefficient. This is what I see it doing:
select max(ids_.id) from ( select id from SubclassAs union select id from SubclassBs union select id from SubclassCs ) ids_
Which takes over 12 seconds to run. Each of those tables has more than a million records each. It's unioning every single ID together and then selecting the max out of that.
If i do something like this:
select max(ids_.id) from ( select max(id) as id from SubclassAs union select max(id) as id from SubclassBs union select max(id) as id from SubclassCs ) ids_
It is much faster, less than one millisecond, because the inner union only gets the max from each table, and then i select just the max out of those 3 records.
Is there a way to tell hibernate to do this instead, or is there a better way of using a generator for the ID across these 3 tables?
Thanks
If increment doesn't satisfy you, you can use some other generator strategy, and, since MySQL doesn't support sequences, the next suitable option is a hilo strategy.
I'm wondering why hibernate generates 1 delete per entity on a child table
instead of using one delete on the foreign key
Here's the hibernate.cfg.xml (No i's not the next SO :-t
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.url">jdbc:hsqldb:file:testdb;shutdown=true</property>
<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.connection.pool_size">0</property>
<property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hbm2ddl.auto">auto</property>
<mapping file="entities/Question.hbm.xml"/>
<mapping file="entities/Answer.hbm.xml"/>
</session-factory>
Question.hbm.xml
<hibernate-mapping>
<class name="entities.Question">
<id name="id">
<generator class="native" />
</id>
<property name="title" not-null="true">
</property>
<property name="question" type="text" not-null="true">
</property>
<bag name="answers" inverse="true" cascade="all,delete-orphan" >
<key>
<column name="questionId" index="answer_questionId_idx" not-null="true"/>
</key>
<one-to-many class="entities.Answer" />
</bag>
<property name="created" update="false" >
<column name="created" not-null="true" index="answer_created_idx"></column>
</property>
<property name="lastUpdated">
<column name="lastUpdated" not-null="true" index="answer_lastUpdated_idx"></column>
</property>
</class>
</hibernate-mapping>
Answer.hbm.xml
<hibernate-mapping>
<class name="entities.Answer">
<id name="id">
<generator class="native" />
</id>
<property name="answer" type="text" not-null="true">
</property>
<property name="created" update="false" >
<column not-null="true" name="created" index="question_created_idx"></column>
</property>
<property name="lastUpdated" >
<column name="lastUpdated" not-null="true" index="question_lastUpdated_idx"></column>
</property>
<many-to-one name="question" column="questionId" not-null="true" update="false">
</many-to-one>
</class>
</hibernate-mapping>
There's 1 Question and 2 answers in my database, this test code:
Session session = factory.openSession();
Transaction t = session.beginTransaction();
Question q = (Question) session.load(Question.class,1);
session.delete(q);
t.commit();
session.close();
I would expect it to generate SQL like,
select .... from Questions where id = 1;
delete from Answers where questionId=1;
delete from Question where id=1;
I.e., just issue one delete to do the cascading delete on Answers,
instead it's loading all the answers and issuing one delete per answer, like:
select
question0_.id as id0_0_,
question0_.title as title0_0_,
question0_.question as question0_0_,
question0_.created as created0_0_,
question0_.lastUpdated as lastUpda5_0_0_
from
Question question0_
where
question0_.id=?
select
answers0_.questionId as questionId0_1_,
answers0_.id as id1_,
answers0_.id as id1_0_,
answers0_.answer as answer1_0_,
answers0_.created as created1_0_,
answers0_.lastUpdated as lastUpda4_1_0_,
answers0_.questionId as questionId1_0_
from
Answer answers0_
where
answers0_.questionId=?
delete from Answer where id=?
delete from Answer where id=?
delete from Question where id=?
How come, and is there anything I can do about it ?
Edit, in response to Nate Zaugg, I can get the db to do the cascading delete by setting on-delete="cascade" on the one-to-many key mapping, i'm more wondering why hibernate does what it does and not does one delete on the Answers table, and wheter threre's something wrong with my mappings.
Can you not configure your DMBS to do cascading deletes on relationships? It's really easy to do.
Edit: Try this <one-to-many class="entities.Answer" lazy="false" cascade="all" />