What is the purpose of custom meta tags? I have seen them at class level and at property level.
Example of Propery level level:
</property>
<property name="name" column="name" type="string">
<meta attribute="Test"/>
</property>
Example of class level
<class name="mypackage.user" table="user">
<meta attribute="Test"/>
......
....
</class>
How does hibernate use this custom values in meta tag?
In Hibernate, custom meta tags used while generating Java POJOs from hbm config file.
Refer https://docs.jboss.org/tools/archive/3.0.1.GA/en/hibernatetools/html/codegen.html. Note that there is a list of Supported meta tags.
Related
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.
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.
The code is as follows:
I want to generate an entity class TermData which is present within the component class, but I'm unable to do that. TermData isn't generated.
<component name="term_" class="Term">
<meta attribute="generated-class" inherit="false">TermData</meta>
<meta attribute="extends">Entity</meta>
<meta attribute="scope-set" inherit="false">protected</meta>
<property name="duration_" column="DURATION" type="int" />
<property name="durationUnits_" column="DURATION_UNITS" type="string" length="64" />
</component>
I'm using hibernate-3.2.6.GA.jar, hibernate-tools-3.2.3.GA.jar with Java 8 and Ant 1.9
Got the problem...there was other component of class class="Term" written in different hbm file which was causing the problem as the genearted-class for that was "Dummy"...so once i changed generated-class at both places as same...it fixed my problem...may be it was due to the order in which it was being processed....as it already generated a component of same class , so it didn't generate the other one.
I was looking over this post of using JSR-303 to validate a collection of objects. The solution works great with annotations, but I can't seem to get it to work with the Hibernate Validator XML formatted configuration.
For example, I have code similar to this:
public class DataSet
{
Collection<Data> dataCollection;
public Collection<Data> getDataCollection() {...}
}
From there, I have a custom validator/annotation DataValidator/#ValidData.
In XML, I do this first:
<bean class="DataSet"
ignore-annotations="true">
<field name="dataCollection">
<valid/>
<constraint annotation="ValidData"/>
</field>
</bean>
However, I get the following exception:
Exception in thread "main" javax.validation.UnexpectedTypeException: No validator could be found for type: java.util.Collection<DataSet>
So I swap the <valid> tag with the <constraint> one in the XML. It seems this is not valid with the XSD schema and the XML can no longer be parsed.
<bean class="DataSet"
ignore-annotations="true">
<field name="dataCollection">
<constraint annotation="ValidData"/>
<valid/>
</field>
</bean>
Exception in thread "main" javax.validation.ValidationException: Error parsing mapping file.
Does anyone know how I can use XML to validate this collection with must custom validator?
The key was adding a class-level constraint annotation in the XML to the Data POJO itself.
<bean class="DataSet"
ignore-annotations="true">
<field name="dataCollection">
<valid/>
</field>
</bean>
<bean class="Data" ignore-annotations="true">
<class>
<constraint annotation="ValidData"/>
</class>
</bean>
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>