Hibernate 4.3.0 XML Mapping Escape Characters Exception - java

In my User.hbm.xml I have:
<property name="delete" type="java.lang.String">
<column name="`delete`" />
</property>
I've also tried with '' and [] but all give the same exception:
org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"delete"
If I change the column name from delete to deletea then it works so I know that it's not escaping the column name properly.

You could try setting this property to automatically quote all identifiers:
hibernate.globally_quoted_identifiers=true

Just try changing this
<column name="`name`" />
to this
<column name="name" />

Related

Hibernate 5 and HBM Mapping issue, Schema-validation: missing table

I am taking an existing Java application and working on updating it from Hibernate 3 where we used hbm.xml files for Entity Mappings. We are now using Hibernate 5.5.5.Final and the code compiles with ehcache, but now I get an error with the code when starting to run it.
I should start off that one of the Hibernate properties is:
validate
The error message I am getting now is:
org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [my_db_dev.Project_myTemplateInfos]
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateTable(AbstractSchemaValidator.java:121)
at org.hibernate.tool.schema.internal.GroupedSchemaValidatorImpl.validateTables(GroupedSchemaValidatorImpl.java:42)
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.performValidation(AbstractSchemaValidator.java:89)
at org.hibernate.tool.schema.internal.AbstractSchemaValidator.doValidation(AbstractSchemaValidator.java:68)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:200)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:81)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:327)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:471)
I would love to completely remove all the hbm.xml files and replace with them with Entity Mapping POJO's with annotations, however, that is not an option right now. The existing application has this different object model that goes throughout, so I don't want to mess with that right now. That will be in the next phase.
According to the error I am missing a table named 'Project_myTemplateInfos' and there is no table with this name. Instead, there is a table named 'Project' and the hbm.xml file for this is as follows.
<hibernate-mapping package="com.myApp.server.model">
<class name="Project" table="project" dynamic-update="true">
<id name="id" column="id">
<generator class="native" />
</id>
<property name="name" not-null="true"/>
<property name="displayCity" not-null="true"/>
<list name="myTemplateInfos" cascade="all, delete-orphan" lazy="false" >
<key column="projectId" not-null="false" />
<list-index column="listIndex" />
<composite-element class="com.myApp.server.model.MyTemplateInfo" >
<property name="name" not-null="false" />
<property name="frequency" not-null="false" />
</composite-element>
</list>
</class>
</hibernate-mapping>
As you can see 'myTemplateInfos' is a List within the Project table. After the POJO is created, it looks like something like this.
#ModelBean(IProject.class)
#PermissionIdentifier("project")
public class Project extends ModelObject implements Serializable, IProject {
private Long id;
private String displayCity = "";
private List<IMyTemplateInfo> myTemplateInfos = Lists.newArrayList();
// getters and setters
// hashcode and equals
}
Next we do have another table in the database that is called 'myTemplateInfos' and we do have an hbm xml file for that table as follows ... actually we do not have an hbm xml file for this, so maybe that is the issue. I am going to create a hbm xml file for this and see if that solves the problem.
We do have a POJO for this object 'MyTemplateInfo' though.
If I simply remove his List from the hbm mapping and the Project object, the problem goes away of course, but there is another Set in the hbm.xml file which would give me the same problem, but with a new missing table.
The question becomes how to fix this error message. Is the problem within the hbm xml file for 'Project', or is it in the Project POJO, or the fact that an hbm file does not exist for the 'MyTemplateInfo'?
The solution to this was to fix the hbm xml mapping. Since I haven't had to do this in over 15 years, I am very rusty with it. I can't tell you how happy I was back then to switch to Java POJO's for Hibernate Entity classes with Annotations. But now, unfortunately, I am back having to deal with these xml files again.
The table I had 'mycommunitytemplateinfos' I created a new hbm xml file for it as follows, and put this in the hibernate.cfg.xml file before the other hbm xml mapping.
<hibernate-mapping package="com.myapp.server.model">
<class name="MyTemplateInfo" table="mytemplateinfos">
<id name="id" column="projectId">
<generator class="native"/>
</id>
<property name="name" not-null="false" />
<property name="frequency" not-null="false" />
</class>
</hibernate-mapping>
The mapping between this and the actual class is fine as I have tested this out. I put the hbm file in the hibernate.cfg.xml file before the Project.hbm.xml file and modified the Project.hbm.xml with a one-to-many tag as follows:
<list name="myTemplateInfos" cascade="all, delete-orphan" lazy="false" >
<key column="projectId" not-null="false" />
<list-index column="listIndex" />
<one-to-many class="com.myApp.server.model.MyTemplateInfo" />
</list>
And this seemed to work. I had to do something like this a few times until I got the mapping right. In this day of age, there isn't a lot of information about hbm xml files. Hibernate 5 does use these, but I understand that the preferred way is annotated Java POJO's. Unfortunately, I am stuck in a situation where I can't do that yet.

how to exclude the dirty data which would lead to SQLException by hibernate

Please find the following mapping xml,
<class name="com.fabulous.A" table="f_a">
<id name="id" column="id">
<generator class="assigned" />
</id>
<property name="startTime" column="start_time" />
</class>
I query table f_a by batch as below, the batch size is 100:
"FROM A WHERE id IN (:ids)"
However there is a dirty row in table f_a which would lead to SQLException, and the whole batch will be failed to get.
I have only select privilege and can't delete the dirty data from DB, is there any way from hibernate to exclude the dirty data automatically by hibernate?
Yes, if query by id one by one I can make it from my application but it's inefficient and unavailable.
Could anyone help with this?
The dirty data is timestamp valued "0000:00:00".
Thanks.
Add an option <property name="hibernate.connection.zeroDateTimeBehavior">convertToNull</property>
to your hibernate.cfg.xml:
Or in hibernate.properties:
hibernate.connection.zeroDateTimeBehavior=convertToNull
I fixed it with appending ?zeroDateTimeBehavior=convertToNull on the jdbcUrl.
You may find my jdbcUrl as below
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/testdb?zeroDateTimeBehavior=convertToNull" />

Exception occurs if the position of discriminator tag in hibernate is moved down

I am new to Hibernate. I am trying to map both my super-class and sub-class to a single table.
<class name="Employee" table="EmpWithManager">
<id name="id" column="ID">
<generator class="native"></generator>
</id>
<discriminator column="EMP_TYPE" type="string"></discriminator>
<property name="firstName" column="FIRST_NAME"></property>
<property name="lastName" column="LAST_NAME"></property>
<property name="salary" column="SALARY"></property>
<subclass name="Manager" extends="Employee">
<property name="managerId" column="MAN_ID"></property>
<property name="noOfEmployees" column="NUMBER_EMP"></property>
</subclass>
</class>
This works fine but if change the position of the discriminator tag as follows:
<class name="Employee" table="EmpWithManager">
<id name="id" column="ID">
<generator class="native"></generator>
</id>
<property name="firstName" column="FIRST_NAME"></property>
<discriminator column="EMP_TYPE" type="string"></discriminator>
<property name="lastName" column="LAST_NAME"></property>
<property name="salary" column="SALARY"></property>
<subclass name="Manager" extends="Employee">
<property name="managerId" column="MAN_ID"></property>
<property name="noOfEmployees" column="NUMBER_EMP"></property>
</subclass>
</class>
This re-ordering gives me the below exception:
Caused by: org.xml.sax.SAXParseException: The content of element type "class" must match "(meta*,subselect?,cache?,synchronize*,comment?,tuplizer*,(id|composite-id),discriminator?,natural-id?,(version|timestamp)?,(property|many-to-one|one-to-one|component|dynamic-component|properties|any|map|set|list|bag|idbag|array|primitive-array)*,((join*,subclass*)|joined-subclass*|union-subclass*),loader?,sql-insert?,sql-update?,sql-delete?,filter*,fetch-profile*,resultset*,(query|sql-query)*)".
Please anybody tell me why this is happening and whether the position of discriminator should be in the beginning?
If you look at the http://hibernate.org/dtd/ entry for hibernate-mapping-3.0.dtd it defines the class element as follows. Order is important as this is a DTD. Note that discriminator? comes after (id|composite-id) and before the long entry with property. This ordering requirement is not explicitly mentioned in the (current) hibernate documentation.
<!ELEMENT class (
meta*,
subselect?,
cache?,
synchronize*,
comment?,
tuplizer*,
(id|composite-id),
discriminator?,
natural-id?,
(version|timestamp)?,
(property|many-to-one|one-to-one|component|dynamic-component|properties|any|map|set|list|bag|idbag|array|primitive-array)*,
((join*,subclass*)|joined-subclass*|union-subclass*),
loader?,sql-insert?,sql-update?,sql-delete?,
filter*,
fetch-profile*,
resultset*,
(query|sql-query)*
)>
According to the hibernate document type definitions (DTD) listed here, the position of the discriminator tag must be after the id tag. Essentially the structure of the xml document in this situation is pre-defined, and you must follow the pre-defined format, and that is why you see an error after moving the discriminator tag.
From the JBoss docs:
5.1.8 - Discriminator:
The <discriminator> element is required for polymorphic persistence using the table-per-class-hierarchy mapping strategy and declares a discriminator column of the table. The discriminator column contains marker values that tell the persistence layer what subclass to instantiate for a particular row. A restricted set of types may be used: string, character, integer, byte, short, boolean, yes_no, true_false.
I'd imagine that you must define how properties will be discriminated against before you define them and that is the reasoning for the structure within the DTD.

org.jumpmind.db.model.ModelException: Unknown JDBC type DATETIME

I am using this XML document to load a specific table into a postgresql database:
create_table.xml:
<?xml version="1.0"?>
<!DOCTYPE database SYSTEM "http://db.apache.org/torque/dtd/database.dtd">
<database name="sample">
<table name="Location">
<column name="LocationID" type="INTEGER" primaryKey="true" />
<column name="LocationModifyDate" type="DATETIME" required="true" />
</table>
</database>
But when I load it, I get an exception:
An exception occurred. Please see the following for details:
-------------------------------------------------------------------------------
org.jumpmind.db.model.ModelException: Unknown JDBC type DATETIME
at org.jumpmind.db.model.Column.setMappedType(Column.java:283)
at org.jumpmind.db.io.DatabaseXmlUtil.nextTable(DatabaseXmlUtil.java:202)
at org.jumpmind.symmetric.io.data.reader.XmlDataReader.readNext(XmlDataReader.java:139)
at org.jumpmind.symmetric.io.data.reader.XmlDataReader.open(XmlDataReader.java:75)
at org.jumpmind.symmetric.io.data.DataProcessor.process(DataProcessor.java:84)
at org.jumpmind.symmetric.io.data.DataProcessor.process(DataProcessor.java:78)
at org.jumpmind.symmetric.io.data.DbImport.importTablesFromXml(DbImport.java:208)
at org.jumpmind.symmetric.io.data.DbImport.importTables(DbImport.java:154)
at org.jumpmind.symmetric.DbImportCommand.executeWithOptions(DbImportCommand.java:188)
at org.jumpmind.symmetric.AbstractCommandLauncher.execute(AbstractCommandLauncher.java:130)
at org.jumpmind.symmetric.DbImportCommand.main(DbImportCommand.java:72)
The command I use to load the XML file is this:
../bin/dbimport --engine corp-000 -format XML create_table.xml
If I use INTEGER rather than DATETIME, the XML file is processed correctly and the table is created.
What does this exception mean? Maybe I have to use a JDBC Standard datatype?
Use timestamp instead of DATETIME
<column name="LocationModifyDate" type="TIMESTAMP" required="true" />
Read the manual for date/time in postgresql here:
http://www.postgresql.org/docs/9.1/static/datatype-datetime.html

How to add collections to a data transfer class in Hibernate

I have the following setup where a class contains a collection. When querying instances of this class I like to populate a data transfer class rather than the data class. However, Hibernate generates a wrong SQL query. What am I missing?
The Hibernate mapping:
<class name="Thread" table="tbl_threads" schema="dbo">
<id name="Id" type="integer">
<column name="i_id"/>
<generator class="identity"/>
</id>
<set name="keywords" inverse="true" lazy="false" cascade="all-delete-orphan" optimistic-lock="false">
<key>
<column name="thread_id" not-null="true"/>
</key>
<one-to-many class="Comment"/>
</set>
<!-- ... -->
</class>
and
<class name="ThreadKeyword" table="tbl_keywords" schema="dbo">
<composite-id name="id"
class="se.ericsson.eab.sdk.fido.server.api.pojos.report.ReportThreadKeywordId">
<key-property name="keywordId" type="integer">
<column name="keyword_id" />
</key-property>
<key-property name="threadId" type="integer">
<column name="thread_id" />
</key-property>
</composite-id>
<!-- ... -->
</class>
The HQL I am using is
SELECT new Composite(t.id, t.keywords, ...)
FROM Thread t, ThreadKeyword tk
WHERE t.id = tk.id.threadId
This generates a SQL where the SELECT part contains only a dot for the keyword attribute:
select thread1_.report_id as col_0_0_, . as col_92_0_
from dbo.tbl_thread reportthre0_ inner join
dbo.tbl_keywords keywords4_ on reportthre0_.i_id=keywords4_.thread_id
It works fine when I query for the data class directly, i.e.
SELECT t
FROM Thread t, ThreadKeyword tk
WHERE t.id = tk.id.threadId
As I understand will Hibernate not find a column name for keywords in the thread table. That is right, since it is a collection. It rather needs to be populated using subsequent queries. If I omit the keywords in the constructor for the Composite class the query gets right but Hibernate won't populate the Set.
How do I get the keywords set populated?
You cannot do that with a collection.
t.id is a column/value
so Hibernate translates that into thread1_.report_id as col_0_0_. Hibernate even gave it the alias col_0_0_
t.keywords is a set of values so Hibernate just can't translate the collection into a column/value.
A query includes a list of columns to be included in the final result
immediately following the SELECT keyword - Wikipedia
Now the
SELECT t FROM Thread t, ThreadKeyword tk WHERE t.id = tk.id.threadId
works fine because Hibernate knows how to translate the query you have there into SQL.

Categories

Resources