Splitting Hibernate configuration files (hbm.xml files) when using subclasses - java

we have a hibernate mapping file (hbm.xml file) that maps a part of our domain to the database. This part contains a inheritance hierarchy. I.e. we have a parent class 'Parent' and several subclasses 'Child1', 'Child2', ...
Because of the structure of the hibernate mapping file the child classes are located within the parents <class> XML tag as <joined-subclass>.
Since this mapping file becomes larger and larger we now want to split it. Is there a way to have a mapping file for each subclass?

The tag in the new XML:
<joined-subclass />
Or
<hibernate-mapping>
<subclass name="DomesticCat" extends="Cat" discriminator-value="D">
<property name="name" type="string"/>
</subclass>
</hibernate-mapping>
Extracted from the hibernate site:
It is possible to define subclass, union-subclass, and joined-subclass mappings in separate mapping documents directly.
Ref: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/inheritance.html
Udo

You can use ENTITY definitions in your XML:
In your main hbm.xml file:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" [
<!ENTITY subclass1 SYSTEM "classpath://my/hbms/subclass1.xml">
<!ENTITY subclass2 SYSTEM "classpath://my/hbms/subclass2.xml">
]>
<hibernate-mapping>
<class name="my.pkg.Parent">
...
&subclass1;
&subclass2;
</class>
And my/hbms/subclass1.xml:
<joined-subclass name="subclass1">
<!-- all the subclass definitions -->
</joined-subclass>
And my/hbms/subclass2.xml:
<joined-subclass name="subclass2">
<!-- all the subclass definitions -->
</joined-subclass>

Related

Hibernate 3.3: how to map list of enums by name

I am working on a project with legacy code and a tight deadline. This application uses Hibernate 3.3.1.GA and XML configurations. It MIGHT be possible to upgrade to a newer version of Hibernate and to integrate JPA to enable the AttributeConverter<Value, Representation> solution I have seen in other questions (like this one), but I really need the path of shortest resistance.
I have an entity that will have a one-to-many relationship with a value that is represented in my Java code as an enum. I have created the table that is supposed to capture the many side as follows:
CREATE TABLE theValueMapping (
id int unsigned NOT NULL AUTO_INCREMENT,
entity int unsigned NOT NULL,
listIndex int unsigned NOT NULL,
value VARCHAR(4) NOT NULL,
PRIMARY KEY (id),
CONSTRAINT FK_theValueMapping_entity FOREIGN KEY (entity) REFERENCES entityTable (id),
UNIQUE UNIQUE_theValueMapping_entity_listIndex_pair (entity, listIndex),
UNIQUE UNIQUE_theValueMapping_entity_value_pair (entity, value)
);
Naturally, my entity has a field that stores a list of the enum instances:
package com.example;
public class TheEntity {
private List<TheValue> theValues;
// everything else dropped, but there are getters and setters
}
And assume the enum is simple:
package com.example;
public enum TheValue {
A,
B,
C;
}
I need to get this mapping to work through XML Hibernate configuration. The best I have been able to devise lets the application launch but fails to load any records:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.example.TheEntity" table="entityTable" lazy="false">
<list name="theValues" table="theValueMapping">
<key column="entity" />
<list-index column="listIndex" />
<element
column="value"
length="4"
type="com.example.TheValue"
not-null="true"
/>
</list>
</class>
</hibernate-mapping>
How can I configure this so Hibernate will load a list of these enum values into my entity from the database?
The answer turned out to be a combination of a typedef approach I had previously rejected plus an inclusion of a missing dependency.
I had not realized that org.hibernate.type.EnumType is defined in the Hibernate Annotations JAR, so I added
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>${hibernate.version}</version>
</dependency>
to my POM.
Then, I reworked my Hibernate configuration to use a typedef to map my enum through this type:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<typedef name="TheValue" class="org.hibernate.type.EnumType">
<param name="enumClass">com.example.TheValue</param>
<param name="type">12</param>
</typedef>
<class name="com.example.TheEntity" table="entityTable" lazy="false">
<list name="theValues" table="theValueMapping">
<key column="entity" />
<list-index column="listIndex" />
<element
column="value"
length="4"
type="TheValue"
not-null="true"
/>
</list>
</class>
</hibernate-mapping>
My thanks to grimarr from the Hibernate forums for showing that I needed hibernate-annotations.jar and to Mike from SO for showing that the typedef approach should work.

Insert Stored Procedure mapped with Hibernate

I'm trying based on some examples and Hibernate documentation for mapping a Stored Procedure, I just need to insert some data wich is not for a single table, but I got the message:
Could not parse mapping document from resource
The mapping file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Data">
<id column="col_id" name="dataId">
<generator class="assigned" />
</id>
<property column="col_liq" name="dataLiq" />
<property column="col_td" name="dataTd" />
<property column="col_numdcto" name="dataNumDoc" />
<sql-insert callable="true" check="none">
{call sp_update_data(?,?,?,?)}
</sql-insert>
</class>
</hibernate-mapping>
The "Data" object is just a POJO.
I will appreciate any idea or sugestion.
just to let others to know how it works due finally I did it.
The mapping is correct with just one point, Hibernate will set the Id as the last field, so the procedure should get it in that position, at least that you do some "trick".
In Java when calling the procedure is like a normal save, the rest is like working with a normal entity.

Hibernate subclass query : Java.lang.object cannot be cast to, ERROR

I have three Java Class, A which is the parent and B & C are subclasses of A. I have a Hibernate mapping file for A where I have mapped B & C using joined-subclass. Now when I try to query C I get [Ljava.lang.Object; cannot be cast to A. The query that Hibernate generates is correct but why it is not allowing the casting to A?
I have tried the following queries, both result in the same error.
session.createQuery("from Request as req inner join req.category where req.class=Externalrequest and req.requestId=:id");
session.createQuery("from ExternalRequest as ereq inner join ereq.category where ereq.requestId=:id");
Where Request is the parent class and ExternalRequest & InternalRequest are the child class.
And here is the basic structure of my mapping file
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Request" table="request" schema="public">
<id name="requestId" type="integer">
<column name="request_id" />
<generator class="sequence" >
<param name="sequence">request_request_id_seq</param>
</generator>
</id>
<many-to-one name="category" column="category" class="RequestCategory" />
<joined-subclass name="ExternalRequest" table="external_request">
<key column="request_id"/>
.........
</joined-subclass>
<joined-subclass name="InternalRequest" table="internal_request">
<key column="request_id"/>
.......
</joined-subclass>
</class>
[Ljava.lang.Object; is the string representation of an array of Objects.
I think what is happening is that you are trying to assign the result of the query, that is an array of Request or ExternalRequest, to a variable of class Request or ExternalRequest.

Hibernate one to one mapping issue

I am trying to creating java web application which depends on several java projects. I need to refer to DTO class in another project, for hibernate mapping file. But while running the application with tomcat, I get persistent class not known: exception.
My DTO and hbm file structure in projects are like following,
common-api/java/src/com/test1/dto/Manager.java (package - com.test1.dto)
common-api/java/config/hibernate/manager.hbm.xml
new-api/java/src/com/test2/dto/Depeartment.java (package - com.test2.dto)
new-api/java/config/hibernate/department.hbm.xml
Department DTO classes has a Manager objec as a property.
public Class Department {
private Manager manager;
}
Department hibernate mapping file contains,
<hibernate-mapping>
<class name="com.test2.dto.Department" table="department">
<id name="id" column="id" type="integer">
<generator class="increment" />
</id>
...
<one-to-one name="manager" class="com.test1.dto.Manager" cascade="save-update" >
</one-to-one>
</class>
Seems the class attribute value is not resolved by hibernate. It's highly appreciate if you guys can suggest me what I can do for this ?
Just include all mapping files in your top level hibernate.cfg.xml , eg:
<hibernate-configuration>
<session-factory ... >
<mapping resource="org/hibernate/auction/Item.hbm.xml"/>
<mapping resource="org/hibernate/auction/Bid.hbm.xml"/>
</session-factory>
</hibernate-configuration>
See http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/session-configuration.html#configuration-xmlconfig

Generated column and table names in hibernate with underscore

how do I force hibernate to generate db schema such that it converts CamelCase into Underscores (using HBM)? Eg. I have:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cz.csas.pdb.be.model.product.passive">
<class name="foo.BarBaz">
<id name="barBazId">
<generator class="sequence"/>
</id>
<property name="extractContactType"/>
<!-- ... -->
</class>
</hibernate-mapping>
And I want hibernate to create table like this (oracle):
CREATE TABLE "BAR_BAZ"
(
"BAR_BAZ_ID" NUMBER(19,0) NOT NULL ENABLE,
"EXTRACT_CONTACT_TYPE" VARCHAR2(512 CHAR),
-- PK etc...
)
I know I can use table/column name in the hbm.xml file, but I want to set it globally (both to save time and prevent errors).
ImprovedNamingStrategy should do exactly what you want. See 3.6. Implementing a NamingStrategy.
In JPA 2 (Hibernate 4), it is even more easier, just add:
<property name="hibernate.ejb.naming_strategy"
value="org.hibernate.cfg.ImprovedNamingStrategy" />
to your persistence.xml.

Categories

Resources