JPA 2.1 #ForeignKey in inheritance class - java

I'm migrating to JPA 2.1 and I would like to replace #org.hibernate.annotations.ForeignKey to something in inheritance class.
In fields, ok:
#ManyToOne
#JoinColumn(name = "any_columm_field_id",
foreignKey = #javax.persistence.ForeignKey(name = "any_name_field_fk"))
But in inheritance class, how to do it?
Example code:
Super class
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
#Table(name = "ANY_SUPER_TABLE_NAME")
public abstract class AnySuperClass { }
Specific class
#Entity
#Table(name = "ANY_SPECIFIC_TABLE_NAME")
// TODO Replace to JPA 2.1
// #org.hibernate.annotations.ForeignKey(name = "any_specific_any_super_fk")
public class AnySpecificClass extends AnySuperClass { }
Any help?
Thank you for your time.

According to the doc this should do it:
#Entity
#Table(name = "ANY_SPECIFIC_TABLE_NAME")
#PrimaryKeyJoinColumn(foreignKey = #ForeignKey(name = "any_specific_any_super_fk"))
public class AnySpecificClass extends AnySuperClass { }
It's not easy to find the answer though, with the embedded annotation... it's not obvious where you should be using it.
Not sure this will help you a year later...

Related

Is there multilevel structure in hibernate

How to design following structure of beans if I have to Question which has sub Questions and all questions and subquestions has respective answer. Structure is like
Structure
How I can design this structure in hibernate for achieving functionality in spring boot.
If we take into consideration that these are 3 different tables, what I would think would be an entity of Question
#Entity
#Table("question")
public class Question
then an entity of SubQuestion
#Entity
#Table("sub_question")
public class SubQuestion
with ManyToOne assosiation
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="QUESTION_ID")
private Question question;
and finally a generic class GenericAnswer
#Entity
#Table(name = "answer")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "question", discriminatorType = DiscriminatorType.STRING)
public class GenericAnswer {
which will be extended by 2 classes, QuestionAnswer and SubQuestionAnswer
These 2 classes have a discriminator column to distinguish the table they refer to (question or sub_question)
#DiscriminatorValue("question")
#Entity
public class QuestionAnswer extends GenericAnswer {
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="QUESTION_ID")
private Question question;
and
#DiscriminatorValue("sub_question")
#Entity
public class SubQuestionAnswer extends GenericAnswer {
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="QUESTION_ID")
private SubQuestion subQuestion;
Hope this helps you.

Hibernate: Fetch all records from a single table, regardless of type defined with #DiscriminatorValue

Hibernate has powerful mechanism to make several entities to share same table in the database. For me, being able to fetch all records regardless of the subtypes would be the most important thing. However this doesn't seem to work.
Provided we have some standard setup:
#Entity
#Table(name = "plane")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(
name="planetype",
discriminatorType=DiscriminatorType.STRING
)
public abstract class Plane { ... }
#Entity
#Table(name = "plane")
#DiscriminatorValue("A320")
public class A320 extends Plane { ... }
#Entity
#Table(name = "plane")
#DiscriminatorValue("B777")
public class B777 extends Plane { ... }
What do I need to access all the planes we have on the table?
#Entity
#DiscriminatorValue("")
public class AnyPlane extends Plane { ... } // this doesn't work
#Entity
public class AnyPlane extends Plane { ... } // this doesn't work either
I try to fetch AnyPlanes same way I usually do...
CriteriaBuilder cb = getSession().getCriteriaBuilder();
CriteriaQuery<AnyPlane> q = cb.createQuery(AnyPlane.class);
Root<AnyPlane> root = q.from(AnyPlane.class);
Query<AnyPlane> query = getSession().createQuery(q.select(root)
.where(someRestrictions)
);
return query.list();
...and get empty list, because Hibernate considers even empty string to be a valid denominator. What would I do?
Worth to mention, that the planes already happyly fly up the code stack, and my goal is to refactor the DB layer without introducing much changes. I'm also not keen to use native SQL.
Simple solution I found is to make the AnyPlane to fly on it own, without extending the Plane:
#Entity
#Table(name = "plane")
public class AnyPlane {
... // same fields we would have on the parent
#Enumerated(EnumType.STRING)
#Column(name = "planetype", insertable = false, updatable = false)
private PlaneType planeType;
...
}
public enum LikedEntityType {
A320,
B777
}
Also consider making a common parent for Plane and AnyPlane to avoid the copypaste for the common fields, while not bearing the sins of #DiscriminatorColumn.

Eclipselink JPA + #Mutitenant + #Inheritance Insert Op Failing - Inconsistent Behavior

#MappedSuperClass
public abstract class BaseMappedSuperClass {
#EmbeddedId
private EmbeddedId id;
}
#Entity
#Multitenant(MultitenantType.TABLE_PER_TENANT)
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "typeCol")
public abstract class Vehicle extends BaseMappedSuperClass{
private String name;
}
#Entity(name = "Cycle")
#Multitenant(MultitenantType.TABLE_PER_TENANT)
#DiscriminatorValue(value = "Cycle")
public class Cycle extends Vehicle {
private String bellType;
}
#Entity(name = "Bus")
#Multitenant(MultitenantType.TABLE_PER_TENANT)
#DiscriminatorValue(value = "Bus")
public class Bus extends Vehicle {
private String gearType;
}
I have the above entity structure and if I try to do an insert op on the entity Cycle or Bus, it fails inconsistently, because of the missing primary key field (id).
When I tried to debug the JPA codebase, I figured that the tenant discriminator, which is tenant_id in my case is not appended to the table name prefix for the embeddedId field 'Id' and the discriminator column field 'typeCol'.
What is more interesting is that this behavior is not consistent. If I restart my application and try, it works. If I restart again and try,it does not work.
Any help would be appreciated. Version of eclipse link used is 2.5.1.
What is the logic behind the order in which the entities are processed to initialize the metadata?

Unnable to save discriminator value. (JPA spring data + hibernate)

I have following situation:
Base class:
#Entity(name = "BaseEntity")
#Inheritance(strategy= InheritanceType.JOINED)
#DiscriminatorColumn(name="DISCR_COLUMN", discriminatorType = DiscriminatorType.STRING)
#Table(name = "base")
#DiscriminatorOptions(insert = true,force=true)
public abstract class Base implements Serializable {
Subclass:
#Entity(name = "SubclassEntity")
#DiscriminatorValue("A")
#Table(name="subclass")
#PrimaryKeyJoinColumn(name = "subclass_id", referencedColumnName = "base_id")
#DiscriminatorOptions(insert = true,force=true)
public class Subclass extends Base {
Repository:
public interface BaseRepository extends JpaRepository<Base, String>, JpaSpecificationExecutor<Base> {
The only problem I have is when I want to create a new Subclass
repository.saveAndFlush(Base base);
discriminator value is not saved and in DB appears NULL. I supposed it is set automatically by hibernate, isn't it ?
Attention: see comment below (!)
According to http://en.m.wikibooks.org/wiki/Java_Persistence/Inheritance section "Joined, Multiple Table Inheritance":
Hibernate does not support discriminator column for inheritance strategy: joined.

javax.persistence annotations and inheritance

I have 4 persistent classes which all have the same fields (exactly) the only 3 difference between them is 1) the class name, 2) the table name and 3) the data. i am aware that this might seem strange to some but trust me there is a good reason which i won't go into here.
now, i'm using hibernate annotations to configure my class which should work like so:
#Entity
#Table(name = "store")
public class Store
{
#Id
#Column(name = "unique_id")
protected String id;
#Column
protected String category;
...
}
.. and this does work, for a single stand-alone class, however there are many fields to map and i'd like to do it all in one hit for all four similar classes, ie:
public class StoreBase
{
#Id
#Column(name = "unique_id")
protected String id;
#Column
protected String category;
...
}
#Entity
#Table(name = "store1")
public class Store1 extends StoreBase
{}
#Entity
#Table(name = "store2")
public class Store2 extends StoreBase
{}
#Entity
#Table(name = "store3")
public class Store3 extends StoreBase
{}
#Entity
#Table(name = "store4")
public class Store4 extends StoreBase
{}
however when attempting this i get the following exception:
Caused by: org.hibernate.AnnotationException: No identifier specified for entity: package.entities.Store1
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:672)
at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:546)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:291)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1292)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867)
i'm guessing this is because the super class is not being searched for the identifier?
is there a way to utilise inheritance in this context?
thanks, paul.
#MappedSuperclass
public class StoreBase
See docs for more info.
Have a look at #MappedSuperclass.

Categories