How would I map an #Entity with a hbm.xml? - java

I in a situation where I need to override some fields in a #Entity class but I can't edit the class. It just so happens that this #Entity class is mapped in a way that I don't think it's possible to partially override it. I was wondering what would be the steps to overriding this class completely or maybe partially if possible.
The class:
org.broadleafcommerce.profile.core.domain.AddressImpl
I've used a hbm.xml and a orm.xml but I'm not exactly sure how to configure them properly.

The book Pro JPA 2 : Mastering the Java Persistence API notes:
The metadata-complete attribute is an attribute on the entity,
mapped-superclass, and embeddable elements. If specified, all
annotations on the specified class and on any fields or properties in
the class will be ignored, and only the metadata in the mapping file
will be considered as the set of metadata for the class. When
metadata-complete is enabled, the same rules that we applied to
annotated entities will still apply when using XML-mapped entities.
For example, the identifier must be mapped, and all relationships must
be specified with their corresponding cardinality mappings inside the
entity element.
So you will need an entry in your orm.xml like the below, adding all other persistent attributes as required (partial override is not possible).
<entity-mappings>
<entity class="com.Foo" metadata-complete="true">
<table name="FOO"/>
<attributes>
<id name="id"/>
</attributes>
</entity>
</entity-mappings>

Related

Set Hibernate access strategy globally?

According to the Hibernate documentation, the placement of the #Id annotation determines how Hibernate will access the entity (field or accessors)
As a JPA provider, Hibernate can introspect both the entity attributes (instance fields) or the accessors (instance properties). By default, the placement of the #Id annotation gives the default access strategy. When placed on a field, Hibernate will assume field-based access. Place on the identifier getter, Hibernate will use property-based access.
Is it possible to define this globally via a property (To avoid having to place a #Access(AccessType.FIELD) on each entity or embeddable)?
I found this related question, but that is for Spring Boot specifically.
You can create a file called orm.xml and put it to the classpath in directory META-INF.
In that file you can set default values. For example the access type:
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings>
<persistence-unit-metadata>
<access>PROPERTY</access>
</persistence-unit-metadata>
</entity-mappings>
You can find the XML Schema here: https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/resources/org/hibernate/jpa/orm_2_2.xsd

How to override an annotation-defined table name in JPA?

I have tables that have this annotation structure in my application and I use JpaRepository for CRUD operations.
#Entity
#Table(name = "FOO")
public class Foo implements Serializable {
…
}
But I need to override only the table name (not any of the #Column etc. attributes) from an orm.xml or properties file without changing the actual code. I've searched and I couldn't find a way to do it in Spring Data JPA. Am I missing something here or it is not supported?
Firstly, Spring Data is not a JPA provider but simply a 'helper' library providing a wrapper round common persistence operations. The JPA specification however does provide a mechanism for overriding annotations via an XML mapping file. So assuming your provider (Hibernate, EclipseLink, OpenJPA or whatever) fully implements the JPA specification then you should be able to do this.
However it would appear that you cannot override only the table name: unless your column names are mapped to the default values then, as far as I can see, you need to specify each column in the mapping file - which is slightly inconvenient I suppose.
The book Pro JPA 2 : Mastering the Java Persistence API notes:
The metadata-complete attribute is an attribute on the entity,
mapped-superclass, and embeddable elements. If specified, all
annotations on the specified class and on any fields or properties in
the class will be ignored, and only the metadata in the mapping file
will be considered as the set of metadata for the class. When
metadata-complete is enabled, the same rules that we applied to
annotated entities will still apply when using XML-mapped entities.
For example, the identifier must be mapped, and all relationships must
be specified with their corresponding cardinality mappings inside the
entity element.
So you will need an entry in your orm.xml like the below, adding other attributes as required.
<entity-mappings>
<entity class="examples.Foo" metadata-complete="true">
<table name="NEW_FOO"/>
<attributes>
<id name="id"/>
</attributes>
</entity>
</entity-mappings>

Is there any annotation available for eager loading at class level when we are not using any mapping?

Is there any annotation available for eager loading at class level when we are not using any mapping ? I know that this is available in XML configuration where we have
<code>
<class name="A" lazy="false">
</class>
</code>
(I know that association Mapping annotations have attributes as fetch=FetchType.EAGER for applying this to any Entity objects one by one. But, here I am not using any mapping.)
My requirement for eager loading is based on the design pattern I have used in my project which is Template where I have several operations with more than one session created and destroyed, so I require eager loading for using all the operations at one client class.
If class is not associated with any of the other class, and you are using session.get() method, it will load the class eagerly.

Hibernate use same mapping for multiple tables

I have 2 identical DB instances containing FOO_TABLE with the same schema. So, currently I have one class definition per DB instance:
<class name="FooTable" table="FOO_TABLE" entity-name="FooTableInstance1">
<property name="..." column="..." />
<property name="..." column="..." />
....
</class>
<class name="FooTable" table="FOO_TABLE" entity-name="FooTableInstance2">
<property name="..." column="..." />
<property name="..." column="..." />
....
</class>
The problem is that I don't want to copy-paste the properties, as the tables have the same schema. Is it possible to inherit the 2 classes from a base class which contains all the mappings and in the 2 children classes specify different entity-name?
An alternative (and perhaps the correct one if I understand your question correctly) is to use a #MappedSuperclass to define the common mappings. Whether you use this or the suggestion posted previously depends on the data model: for example are these two entities related so that you would like to be able to query across both of them?
e.g. select f from Foo returns all Foo1 and Foo2.
This cannot be done when Foo is a MappedSuperclass.
See here for further details:
http://en.wikibooks.org/wiki/Java_Persistence/Inheritance#Mapped_Superclasses
JPA: Implementing Model Hierarchy - #MappedSuperclass vs. #Inheritance
Yes, it is possible. Take a look at the relevant documentation: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/inheritance.html
More specifically, check 9.1.5. Table per concrete class. Make the parent class abstract and things should work fine.
According to the documentation you need 3 Java classes:
Foo (abstract, containing all fields you want in both tables)
FooChild1 (concrete, subclass of Foo, containing no new fields)
FooChild2 (concrete, subclass of Foo, containing no new fields)
You will need two tables. One mapping to FooChild1, and another to FooChild2.

hibernate simple inheritance - OR - xml property import/include

Final goal:
Have a few java objects sharing the same base class persisted into a database while each one having its own self-contained table with all own/inherited objects, and a simple auto-generated by the database id.
Very simple requirement. Impossible (?) with Hibernate!
What I have so far (using MySQL, Hibernate XML mapping):
map.hbm.xml
<?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 default-access="field"
default-lazy="false">
<class name="xyz.url.hibernate.EntityBase" abstract="true">
<id name="m_id" column="id">
<generator class="identity" />
</id>
<version name="m_version" column="version" type="long" />
<union-subclass name="xyz.url.hibernate.User" table="my_entity">
<property name="name" column="name" type="string" />
</union-subclass>
</class>
</hibernate-mapping>
EntityBase.java
public abstract class EntityBase {
private final long m_id;
private final long m_version;
public EntityBase() {
this.m_id = 0;
this.m_version = 0;
}
public long get_id() {
return this.m_id;
}
public long get_version() {
return this.m_version;
}
}
User.java
public class User extends EntityBase {
public String name;
}
The above does not work unless you change the generator class to increment.
Currently this is the given error:
org.hibernate.MappingException: Cannot use identity column key generation with <union-subclass> mapping for: xyz.url.hibernate.User
Well, why does Hibernate ASSUMES I want a unique ID in a program-wide scope (I've read about some JPA requirement)... what a crap!
Anyway, I insist of having a simple table (per object) that aggregates all the object's (User in this case) properties, and deny using discriminators (again what a crap..) which just complicate the final SQL queries and hit performance.
The only solutions I see here:
Manually map all properties in a one block inside the XML.
Map all properties while "importing" some <propert> items from an external file, thus achieve inheritance (reusage of properties). Possible? How to do?!?
Explore annotations further which as far as I've seen they don't support that simple inheritance requirement.
Dump Hibernate and go with another ORM solution.
Please don't link to the docs - I gave up on that one after reading them a few times!
An example of property import (from external file) would be great.
Thanks and god bless!
First of all you need to decide whether your inheritance relationship should be mapped to the database (to allow polymorphic queries such as from EntityBase, polymorphic realtionships, etc) or not.
As far as I understand in your case it shouldn't be mapped, therefore it doesn't make sense to use inheritance mapping options such as <union-subclass> at all. Now you have the following options:
2. Hibernate doesn't have special support for reuse of XML mappings, but its documentation suggests to use XML entities in this case, see, for example, 10.1.6. Table per concrete class using implicit polymorphism.
3. Annotations certainly support this requirement in form of #MappedSuperclass annotation.
This annotation can be used to mark a class that is not mapped to the database itself, but any mapping annotations defined on its properties take effect for its mapped subclasses, so that you don't need to repeat them.
You can also use XML Entity Reference, see:
https://n1njahacks.wordpress.com/2014/09/19/hibernate-xml-mapping-fragment-re-use/
http://xml.silmaril.ie/includes.html

Categories

Resources