Hibernate one to one mapping issue - java

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

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.

The filter mechanism in Hibernate hbm file is not very flexible for dynamic predicates

I am developing a Spring framework and hibernate application with a central database for an enterprise web application that has
about 1000 users online daily.
You can assume that there is a billing application and anybody can do anything on his own account (e.g. increase the amount of his billing or
decrease the amount of his billing).
Any user has its own data which is secured to the specific user by a mechanism of filtering in hbm files:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping default-lazy="true">
<class name="org.myoffice.Inventory" table="Core_INVENTORY">
<id name="id" column="Id" type="java.lang.Long">
<generator class="sequence" >
<param name="sequence">SEQ_INVENTORY</param>
</generator>
</id>
<many-to-one name="bill" column="bill_ID" entity-name="org.myoffice.Bill" not-null="true" unique-key="unq_StrHouse_Smp_Pn_Exp"/>
<property name="expireDate" column="expire_Date" type="date" unique-key="unq_StrHouse_Smp_Pn_Exp"/>
<many-to-one name="user" column="user_id" entity-name="org.myoffice.User" not-null="true" update="false" />
<many-to-one name="createdBy" column="CreatedBy" entity-name="org.myoffice.User" not-null="true" update="false" />
<many-to-one name="updatedBy" column="UpdatedBy" entity-name="org.myoffice.User" not-null="true" />
<property name="createdDate" column="CreatedDate" type="date" not-null="true" update="false" />
<property name="updatedDate" column="UpdatedDate" type="date" not-null="true"/>
<property name="ip" column="IP" type="string" not-null="true"/>
<filter name="powerAuthorize" condition="[SQL QUERTY IS HERE FOR RESTRICTION ANY USER TO OWN DATA]"/>
</class>
</hibernate-mapping>
NOTE: The end of ([SQL QUERTY IS HERE FOR RESTRICTION ANY USER TO OWN DATA]) in above hbm is finished with a WHERE CLAUSE has userId parameter
for restricting a user to his own data and this userId is added the below method of generic repository.
And I add the powerAuthorize of hbm in my generic repository like this:
public void applyDefaultAuthorizeFilter(Session session) {
Filter filter = session.enableFilter("powerAuthorize");
filter.setParameter("userId", SecurityUtility.getAuthenticatedUser().getId());
}
This filter always add to end of any query for filtering data.
Everything had been working fine until the consumer of my application brought up a new demand which is not compatible with this current design. The consumer now wants to increase the billing of another user.
If I skip the filter hbm, any user will see the information of another user and if i dont skip the filter, I can't implement this new request.
Is there other mechanism, pattern or anything else I could use instead?
The #Filter is useful when the condition does not change, but just the bind parameter value can vary.
What you need here is to filter the WHERE clause predicate. Therefore, you need to move the filtering logic in your data access layer.
You write DAO methods to filter the Inventory based on user rights.
You remove the #Filter since the DAO methods will do that instead.
This design is much more flexible on the long term too.
You can use several filters and enable/disable them on demand. E.g. activate your "powerAuthorize" filter for all requests and just enable another filter "comprehensiveAuthorize" for your new requirement and disable "powerAuthorize" temporary.

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.

JPA xml mapping not finding fields

I have the following class:
package lt.vic.valdos.domain.valda;
public class Valda implements java.io.Serializable {
private long id;
private Long valdosKodas;
public long getId() {
return id;
}
public Long getValdosKodas() {
return valdosKodas;
}
}
and the following orm.xml:
<?xml version="1.0"?>
<entity-mappings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.eclipse.org/eclipselink/xsds/persistence/orm http://www.eclipse.org/eclipselink/xsds/eclipselink_orm_2_1.xsd"
version="2.1">
<entity class="lt.vic.valdos.domain.valda.Valda">
<table name="VALDOS" schema="VLD" />
<attributes>
<id name="id" />
<basic name="id">
<column name="vld_id" />
<return-insert return-only="true" />
</basic>
<basic name="valdosKodas">
<column name="valdos_kodas" />
</basic>
</attributes>
</entity>
</entity-mappings>
When I deploy this in glassfish, i get the following error:
Exception [EclipseLink-7215] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Could not load the field named [id] on the class [class lt.vic.valdos.domain.valda.Valda]. Ensure there is a corresponding field with that name defined on the class.
The class is in a jar that is included into a web application as a maven dependency. The orm.xml is in /WEB-INF/classes/META-INF of the web application.
What am I doing wrong?
Figured this one out myself. For some reason EclipseLink requires a setter on a class. Once I add private setters everything seems fine. Why the setters are needed (mapping accessors should default to FIELD) remains a mystery but it is not that important for me. Adding access="FIELD" to all entity attributes also fixes the problem without the setters.
You should be specifying the id as generated using the IDENTITY strategy:
<id name="id">
<column name="vld_id"/>
<generated-value strategy="IDENTITY"/>
</id>
This strategy will automatically read the database provided id back into the new object upon successful commit. The EclipseLink returning statement functionality is only applicable to basic mappings because id is already covered by Identity ID generation.
I think you have to add the column description for the id column to your id element, instead of using an extra basic element. As in <id name="id"> <column name="vld_id" /> ... </id>, without an extra <basic name="id"> ....
From my own experience (some time ago now), it's probably easier to use annotations to define your mappings.

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

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>

Categories

Resources