Hibernate 5.2 get natural id properties from metamodel - java

Since SessionFactory#getClassMetadata(java.lang.Class) was deprecated, I am not able to use ClassMetadata. I would like to access to the following methods:
org.hibernate.metadata.ClassMetadata#getNaturalIdentifierProperties
org.hibernate.metadata.ClassMetadata#hasNaturalIdentifier
According to the documentation, I should replace getClassMetada with EntityManagerFactory.getMetamodel(). However, the metamodel does not contain methods to get natural-id. I am using xml mapping for natural-id and I would like to get the property names of the natural-id to create a dynamic query.
<class name="User">
<cache usage="read-write"/>
<id name="id">
<generator class="increment"/>
</id>
<natural-id>
<property name="name"/>
<property name="org"/>
</natural-id>
<property name="password"/>
</class>
Is there a way to use those methods to get the natural id mapping?
Is there another way to get a ClassMetadata instance?
Is it possible to get an instance of entityMetamodel to replace the ClassMetadata?

Well, knowing that SessionFactory#getClassMetadata(java.lang.Class) was deprecated, the option is using sessionFactory.getMetamodel(). Checking into hibernate code, this was my solution:
MetamodelImplementor metamodel = (MetamodelImplementor) sessionFactory.getMetamodel();
ClassMetadata classMetadata = (ClassMetadata) metamodel.entityPersister(entityName);
First, one part important to know is what entityName is. It could be the name of the mapped entity or Entity.class.getName(). Knowing that, to replace SessionFactory#getClassMetadata(java.lang.Class) with should get the name of the class and pass it as an string.
String entityName = EntityClass.class.getName();
Second, Hibernate has an implementation of JPA metamodel, named MetamodelImplementor.
Additionally, metamodel.entityPersister() returns an EntityPersister interface. Hibernate implements it using AbstractEntityPersister. And that is an abstract class which implements Lockable and ClassMetadata interfaces.
EntityPersister (interface) --> Lockable (interface) -->
AbstractEntityPersister (abstract class)
ClassMetadata (interface) --> AbstractEntityPersister (abstract class)
So, it is possible to cast AbstractEntityPersister to ClassMetadata. And in that way return same object.
This is a portion of code of Hibernate in SessionFactoryImpl:
public ClassMetadata getClassMetadata(String entityName) throws HibernateException {
return (ClassMetadata) getMetamodel().entityPersister( entityName );
}

Related

Mapping a map collection containing superclasses in Hibernate

I am trying to map a map collection of String, SuperClass using XML mapping files. Here's what I have:
<map name="mapName" cascade="all-delete-orphan">
<key column="ID" />
<index column="KEY" type="string" />
<one-to-many class="SuperClass" />
</map>
The SuperClass has (currently one but probably going to need some more in the future) a subclass that I'm going to call SubClass. So I have a bunch of SubClass and SuperClass objects in the map and when Hibernate attempts to search for them after adding them I get a
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
I'm pretty sure Hibernate is looking for classes of type SuperType when the objects in the map actually have some SubTypes as well.
Here's the gist of how the mapping was done for the hierarchy in case you need a better representation of what I'm talking about:
<class name="SuperClass" table="SUPER_CLASS">
...properties...
(contains some <component> tags as well if it matters)
<union-subclass name="SubClass" table="SUBCLASS">
...more properties...
</union-subclass>
</class>

How to Create DB Context File in hibernate in java like Entity Framework c#

I have been working in .NET using Entity Framework with fluent API.
I created database context with all the relations of entities to map with tables and relations with entities with one to many etc.
I know the annotations way and mapping via XML files.
Following is the code in c#
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.Property(u => u.DisplayName)
.HasColumnName("display_name");
}
}
Can any one tell me how to set a file in hibernate in JAVA to create the Blogs table for entity Blog and set properties for any entity with database rather then creating adding annotations.
Just some suggesions: Hibernate does not have the concept of Context but I usually insert a Context class where I set Hibernate Configuration class (one time for the project) and where I retrieve a session (Configuration.BuildSessionFactory() to get a ISessionFactory one time for the project and then ISessionFactory.OpenSession() or other methods similar to it). A session is the class where you start to build queries and insert/update/delete objects (so the usage is similar to the EF Context - you don't implement a Session like a DbContext -).
Usually you build the mapping using xml files like this
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="FiPlan.Data.Entities" assembly="FiPlan.Engine">
<class name="Account" table="Accounts" >
<id name="Id" column="ID" type="String" length="15" >
<generator class="assigned" />
</id>
<property name="Description" column="Description" type="String" not-null="false" length="50" />
</class>
</hibernate-mapping>
You add this files to the Configuration class (the one where you start to get a session).
Another consideration: there isn't the DbSet concept (every configured class can be accessed via queries).
I know that is not what you are looking for but I hope that this could be an help when you will start to read the Hibernate manual.
In short - I didnt find any way to create mapping or file like context for hibernate like in Entity Framework .NET

Could not determine type for entity

I have two classes:
public ClassAEntity extends ClassA {
private Long id;
#Override
public void doSomething() {
// do something
}
}
public abstract ClassA {
public abstract void doSomething();
}
And the JPA ORM file containing:
<entity class="ClassAEntity" access="FIELD">
<attributes>
<id name="id">
<column name="seqid" />
<generated-value strategy="IDENTITY" />
</id>
</attributes>
</entity>
Yet during initialization I get the following error:
Caused by: org.hibernate.MappingException: Could not determine type
for: com.example.ClassA, at table: ClassAEntity, for columns:
[org.hibernate.mapping.Column(classA)]
But there is no such column! What's wrong with all this? Can't I just have abstract class for my entity?
Finally solved:
Just remember that using JPA mappings (ORM xmls) will make persistence try to map all fields of the Entity by default whereas hibernate mappings do not do this. So check for each field at class level - there might be an unmapped reference to the abstract class as in my case.
My friend please apply, all proper annotation at entity level and field level and Mapping of hibernate like one to one, many to one. then rerun it and get back with your updates
you can refer this site as well
http://www.springbyexample.org/examples/one-to-many-jpa-hibernate-config-jpa-entity-config.html
You can
declare ClassA with Entity
or
declare ClassA as MappedSuperClass : this is the way i recommand, becauce it's seems ClassA does not embed ID.

Hibernate mapping with one-to-many polymorphic relationship

I have the following class diagram and I want to map it to a database (note that Person has a list with objects of class Vehicle).
Also my database looks like:
All tables in the database that represent a subclass of the Vehicle class have all the fields of the superclass Vehicle. Also, all the relations show a one-to-many relationship from Person to Vehicle, Car and Motorcycle.
My hibernate mapping files are the following:
Person.hbm.xml
<hibernate-mapping package="....">
<class name="Person" table="Persons">
<id name="key" column="Person_ID">
<generator class="native"/>
</id>
<list name="ownedVehicles" inverse="false" cascade="all">
<key column="Person_ID" not-null="true" />
<list-index column="idx"/>
<one-to-many class="Vehicle"/>
</list>
</class>
</hibernate-mapping>
Vehicle.hbm.xml
<hibernate-mapping package="...">
<class name="Vehicle" table="Vehicles" polymorphism="implicit">
<id name="id" type="int" column="Vehicle_ID">
<generator class="increment"/>
</id>
<property name="numOfSeats"/>
<union-subclass name="Car" table="Cars"></union-subclass>
<union-subclass name="Motorcycle" table="Motorcycles"></union-subclass>
</class>
</hibernate-mapping>
The problem (error I get) is the following:
Hibernate: insert into Persons (Person_ID) values (default)
2013-06-26 15:41:52 WARN JdbcCoordinatorImpl:424 - HHH000386: ResultSet had no statement associated with it, but was not yet registered
Hibernate: update Car set numOfSeats=? where Vehicle_ID=?
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
I get this error when I run:
Car car = new Car();
car.setNumOfSeats(5);
Person person = new Person();
person.getOwnedVehicles().add(car);
ManagePerson managePerson = new ManagePerson();
Integer personID = managePerson.store(person);
The store() function of ManagePerson actually creates a session and a transaction and then uses the save() method provided by Hibernate to persist the objects into the database.
As far as I understand Hibernate usually will do insert into Persons, then insert into Cars and finally update Cars (the update is done to save the foreign keys on Cars table that will reference the Person that owns the cars). However, here this is not the case and the insert into Cars seems to be getting skipped. I understood how Hibernate works here by trying person.getOwnedVehicles().add(vehicle); instead of person.getOwnedVehicles().add(car); on the code given above.
As you might understand, I am trying to see if Hibernate actually understands in which "subclass" table a record should go, depending on the class of the object contained in the ownedVehicle list of the Person class. For example, if the ownedVehicles has an object of class Car and one of class Motorcycle, then each of these should go to Cars and Motorcycle tables respectively.
Note: I am using Hibernate 4.2.2 and HSQLDB 2.2.9.
I would appreciate any help with this.
Thanks.
I think it is just a matter of incorrect use of the implicit polymorphism of Hibernate.
Implicit polymorphism for your case can only work by changing your list to have
inverse="true". This can be done of course if your Vehicle class also 'knows' about the relationship with the Person class (e.g. by adding an 'Owner' property and the corresponding mapping).
(Have a look at this table and the case of "table per concrete-class (union-subclass)" and one-to-many associations.
If you enable logging and raise the log level to DEBUG you would see that currently Hibernate tries to update the Vehicles table with the Person_ID instead of the Car table like you meant it to. This is because of the inverse="true" and the limitations of the combination of the Table-per-concrete-class mapping strategy and implicit polymorphism (have a look at the documentation).
So, by having the Vehicle class know about its Owner and using inverse="true" you should be able to succeed in what you are trying to do. Either this or try one of the other inheritance mapping strategies (again have a look at the documentation).
If the managePerson.store(...) method doesn't have a recursive call to the objects in "getOwnedVehicles()" such that it can then call their "store" methods then you shouldn't expect that the created "car" object would be inserted into the table.
You are in fact calling "managePerson.store" not "manageCar.store", I'd have to see the code in the .store(...) method to be sure though but I would expect that it is not doing an iteration of the Vehicles and is not doing an insert for any discovered ones (why should it unless you built it explicitly to do that?).

How to map a Map<Calendar,Boolean> with jpa/hibernate

i've got 2 tables:
Seat(roomID,seatID,...)
SeatState(roomID,seatID,date,state)
i wanna create a seat class and i would like this class to have a Map attribute. does somebody know how to map this thing?
Hibernate supports using 'Map's as collections. If you are using hbm.xml files, you can use the <map> tag for this purpose. Take a look at http://docs.jboss.org/hibernate/core/3.3/reference/en/html/collections.html for a reference. Also Hibernate supports mapping Calendar fields to TIMESTAMP fields.
So if you are using XML, it should be something like
<map name="booking" table="BOOKING">
<key column="BOOKING_ID"/>
<map-key column="BOOKING_DATE" type="calendar"/>
<element column="IS_BOOKED" type="boolean"/>
</map>
Likewise, JPA / Hibernate Annotation alternatives also exist. You need to use #Embeddable to get this done. See http://hwellmann.blogspot.com/2010/07/jpa-20-mapping-map.html for an example.

Categories