Fail to map by MappedSuperclass's attribute - java

Entities:
#Entity
#Table(name = "ITEM")
#Inheritance(strategy = InheritanceType.JOINED)
public class Item extends Base {
#OneToOne(mappedBy = "item")
protected Doc doc;
}
#MappedSuperclass
public abstract class Doc extends BaseDoc {
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "itemId")
private Item item;
}
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class BaseDoc extends Base {}
Tables:
BASEDOC
- itemId int8
(other attributes)
ITEM
(other attributes)
BASE
(other attributes)
During runtime it fails with:
Caused by:
org.hibernate.AnnotationException: Unknown mappedBy in: com.ghiton.updater.entity.Item.doc, referenced property unknown: com.ghiton.updater.entity.Doc.item"}}
I think the reason is the MappedSuperclass, since 'item' is stored in the Base table. Is there a practice to solve these type of cases?
I found that "Mapped superclasses can't be targets of entity relationships.", in this case how I can achieve that Doc to be persisted into the BaseDoc table?
At DB level it has all the columns what are needed, so not necessary to have a separate DOC table.

You cant join mappedsuperclass annotated class with entity class. Mappedsuperclases are not an entity
Link
I think you can change your code like this.
#Entity
#Table(name = "ITEM")
#Inheritance(strategy = InheritanceType.JOINED)
public class Item extends Base {
#OneToOne(mappedBy = "item")
protected Doc doc;
}
#Entity
#Table(name = "DOC")
public abstract class Doc extends BaseDoc {
#OneToOne(mappedBy = "doc")
private Item item;
}
#MappedSuperclass
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class BaseDoc extends Base {}

Related

JPA Criteria Builder - getting an attribute that is a list

I'm trying to access an attribute in one of my entity classes: "products" that is a list:
#Entity
#Table(name = "TRANSACTION")
#Getter
#NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Transaction extends BaseTransaction {
...
#OneToMany(mappedBy="transaction)
private List<Product> products;
...
}
#Entity
#Table(name = "PRODUCT")
#Getter
#AllArgsConstructor
#NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Product {
....
#ManyToOne
#PrimaryKeyJoinColumn
#Getter
#NonNull
private Transaction transaction;
....
#Embedded
#AttributeOverrides({
#AttributeOverride(name = "name", column = #Column(name = "seller_name")),
#AttributeOverride(name = "country", column = #Column(name = "seller_country")) })
private NameAndCountry seller;
...
}
#Embeddable
#AllArgsConstructor
#Getter #Setter
#NoArgsConstructor(access = AccessLevel.PRIVATE)
public class NameAndCountry {
private String name;
private String country;
}
Given a string: "myName", and by using JPA criteria builder, I'm trying to retrieve the name of the seller of the transaction, and this is what have when I'm trying to build the predicate:
Join<Object, Object> transactionProductJoin = root.join("products");
Predicate predicate_ = criteriaBuilder.equal(transactionProductJoin.get("products").get("seller").get("name"), "myName");
However I'm facing an error which says:
Unable to locate Attribute with the the given name [products] on this ManagedType [work.my.domain.models.BaseTransaction]
Why is JPA criteria builder trying to retrieve the "products" attribute from the parent class of Transaction? What should be the correct way to construct the predicate?
Following is the example where we map Parent and Child entity classes using JPA Annotations.
#Entity
#Table(name = "Parent")
#Inheritance(strategy = InheritanceType.JOINED)
public class Parent {
// Getter and Setter methods
}
#Inheritance – Defines the inheritance strategy to be used for an entity class hierarchy. It is specified on the entity class that is the root of the entity class hierarchy.
#InheritanceType – Defines inheritance strategy options.
Single table per class hierarchy strategy: a single table hosts all the instances of a class hierarchy
Joined subclass strategy: one table per class and subclass is present and each table persist the properties specific to a given subclass. The state of the entity is then stored in its corresponding class table and all its superclasses
Table per class strategy: one table per concrete class and subclass is present and each table persist the properties of the class and its superclasses. The state of the entity is then stored entirely in the dedicated table for its class.
#Entity
#Table(name="Child")
public class Child extends Parent {
//Getter and Setter methods,
}
#Inheritance(strategy = InheritanceType.JOINED)
Should be added to the parent entity. (Depending on the InheritanceType required for your scenario.)
Check these links for reference:
Chapter 10. Inheritance mapping
5.1.6. Inheritance strategy
The issue is solved, the problem was in the construction of the predicate:
Wrong:
Predicate predicate_ = criteriaBuilder.equal(transactionProductJoin.get("products").get("seller").get("name"), "myName");
Correct:
Predicate predicate_ = criteriaBuilder.equal(transactionProductJoin.get("seller").get("name"), "myName");

How to refer to a parent Object annotated with #MappedSuperclass from a child object?

How can i refer my child object to it's parent which are annotated with #MappedSuperclass? These are my classes:
#MappedSuperclass
public class Person extends BaseEntity {}
#Entity
#Table(name = "employee", catalog = "enrollment_system", uniqueConstraints =
#UniqueConstraint(columnNames = {"reference", "emp_number"}))
public class Employee extends Person implements Serializable{}
#MappedSuperclass
public class BackGroundHistory extends BaseEntity {
#ManyToOne
#JoinColumn(name = "person_id")
#ForeignKey(name = "fk_person_history")
private Person person;
}
#Entity
#Table(name = "educational_history", catalog = "enrollment_system")
public class EducationalHistory extends BackGroundHistory implements java.io.Serializable {}
and during run time, i am getting this error:
Exception in thread "main" org.hibernate.AnnotationException: #OneToOne or #ManyToOne on entities.EducationalHistory.person references an unknown entity: entities.Person
I am doing this, to avoid multiple declaration on BackGroundHistory class since aside from, class Employee I also have class Applicant and class Student.
A mapped super-class is not an Entity, it's just used to extends or for inherit property like a ID , CREATE_TIME , UPDATE_TIME ..etc

Hibernate Inheritance, parent classes should be child or parent based on decider

Trying to achieve inheritance in Hibernate.
Following is schema
Here is What, Classes are,
//Grand Parent Class
#Entity
#Table(name="grand_parent")
public class GrandParent{//consider #id}
//Parent Class
#Entity
#Table(name = "parent")
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name = "decider", discriminatorType = DiscriminatorType.STRING)
public class Parent{//consider #id}
//ChildX class
#Entity
#Table(name = "childX")
#PrimaryKeyJoinColumn(name="id")
#DiscriminatorValue("X")
public class ChildX() extends Parent{//consider value}
//ChildY class
#Entity
#Table(name = "childY")
#PrimaryKeyJoinColumn(name="id")
#DiscriminatorValue("Y")
public class ChildY extends Parent(//consider value){}
//ChildZ class
#Entity
#Table(name = "childZ")
#PrimaryKeyJoinColumn(name="id")
#DiscriminatorValue("Z")
public class ChildZ() extends Parent{//consider value}
Use Case:
If decider is 'K', and 4 records need to be saved then 4 parent records should be added
If decider is 'X/Y/Z', and 4 records need to be saved then, 1 parent record and 4 ChildX/ChildY/ChildZ records should be added.
However, parent table should be treated as single child when decider is 'K' and it must be acted as parent when decider is 'X/Y/Z'
But with above class diagram, Whenever decider is 'X/Y/Z', 4 records saved in ChildX/ChildY/ChildZ and no record in parent table.
Also how to retrieve above records.
EDITS
#Entity
#Table(name="grand_parent")
public class GrandParent{
#OneToMany(mappedBy = "parentRecord",
fetch = FetchType.LAZY,
cascade = CascadeType.ALL)
#Cascade(org.hibernate.annotations.CascadeType.DELETE)
private List<parent> parentList;
}
//Parent Class
#Entity
#Table(name = "parent")
public class Parent{
#ManyToOne()
#JoinColumn(name = "fk_gp_id")
private GrandParent parentRecord;
#OneToMany(mappedBy = "childrecord",
fetch = FetchType.LAZY,
cascade = CascadeType.ALL)
#Cascade(org.hibernate.annotations.CascadeType.DELETE)
private List<Child> childList;
}
#Entity
#DiscriminatorColumn(name = "decider", discriminatorType = DiscriminatorType.STRING)
public abstract class Child(){
#ManyToOne(optional = false)
#JoinColumn(name = "fk_parent_id")
private parent childrecord;
}
//ChildX class
#Entity
#Table(name = "childX")
#DiscriminatorValue("X")
public class ChildX() extends Parent{//consider value}
......
To add..
GrandParent gp = new GrandParent();
Parent p = new Parent();
ChildX ch = new ChildX();
ch.setChildrecord(p);
p.setChildList(//Array added ch);
p.setParentRecord(gp);
gp.setParentList(//Array added p);
persist(gp);
Now I am getting an error:
Application error : com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'Child' doesn't exist
When you use (Joined) inheritance you will always insert a row in both the Parent and Child table when you persist a child. This means that every Parent has at most one child.
In you table diagram, you have multiple children with the same parent, this is not inheritance, this is a OneToMany Entity relationship, which is confirmed by your ER diagram.
My guess is that you are looking for something like this:
#Entity
public class Parent {
#Id
private long id;
#OneToMany(mappedBy = "parent")
private Collection<Child> children;
}
#Entity
#DiscriminatorColumn(name = "decider", discriminatorType = DiscriminatorType.STRING)
public abstract class Child {
#Id
private long id;
#ManyToOne
private Parent parent;
// other common fields
}
#Entity
#DiscriminatorValue("X")
public class ChildX extends Child {
// specific fields for child x
}
// more children types
A parent can have many children, and these children can be of different types. The child base class has the foreign key column referencing the parent, in my experience inheritance base classes often end up being abstract.
EDIT: Here is an example of code that stores a Parent and a specific child.
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
Parent p = new Parent();
ChildX childX = new ChildX();
childX.setParent(p);
em.persist(p);
em.persist(childX);
em.getTransaction().commit();
} finally {
em.close();
}

Query by type in Spring Data JPA

I've abstract class:
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class A {
...
}
and few extending classes, like:
#Entity
public class B extends A {
...
}
I also have third entity:
#Entity
public class C {
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private A objectA;
...
}
And the question is, how can I construct Spring Data JPA finder in C entity repository to query only objects extending A with desired type?
You can use the name of discriminator value which you've defined "type"
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
#Table(name = "abc")
public abstract class Abc {
....
-------------------------------------------
#Query("select a from Abc a where type = ?1")
List<Abc> findByType(String typeValue);

Mapping inherited fields

I'm using EJB 3 with Hibernate 4 on Weblogic 10.3.4.
I have a problem when I try to select an entity based on a property that doesn't exists in its parent entity:
I have in my system something like this: A basic abstract VehicleDefinition class and two concrete subclasses - CarDefinition and TruckDefinition.
Also, I have a basic abstract VehicleInstance and two concrete subclasses - CarInstance and TruckInstance.
In VehicleInstance I have a VehicleDefinition field.
In the TruckDefinition class I map a field (Height) that doesn't exists In VehicleDefinition or in CarDefinition. The problem is that with the mentioned mapping, I can't use an HQL to select a TruckInstance by a the field of TruckDefintion (i.e. A TruckInstance by height), because TruckInstance only "knows" VehicleDefinition, not TruckDefinition.
The mappings goes something like this:
#Entity
#Table(name = "VEHICLES" uniqueConstraints = {#UniqueConstraint(columnNames = {"TYPE_NAME"}) })
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "VEHICLE_TYPE", discriminatorType = DiscriminatorType.INTEGER)
public abstract class VehicleDefinition {...}
#Entity
#DiscriminatorValue("222")
public class CarDefenition extends VehicleDefinition {...}
#Entity
#DiscriminatorValue("555")
public class TruckDefenition extends VehicleDefinition{
...
private Integer mHeight;
#Column(name = "TRUCK_HIGHT")
public Integer getHeight()
{
return mHeight;
}
}
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorFormula("CASE WHEN 222 = (SELECT a.VEHICLE_TYPE FROM VEHICLES a WHERE a.id = VEHICLE_ID) THEN 222 ELSE 555 END")
#Table(name = "VEHICLE_INSTANCES" uniqueConstraints = {#UniqueConstraint(columnNames = {"VEHICLE_ID", "LPLATE"}) })
public abstract class VehicleInstance {
...
private VehicleDefinition mDefinition
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "VEHICLE_ID" referencedColumnName = "ID", nullable = false)
public VehicleDefenition getDefinition()
{
return mDefinition;
}
}
#Entity
#DiscriminatorValue("222")
public class CarInstance extends VehicleInstance {...}
#Entity
#DiscriminatorValue("555")
public class TruckInstance extends VehicleInstance {...}
I tried to refactore he classes, making getDefinition in VehicleInstance abstract, and having TruckInstance and CarInstance implement, both returning their repectivetypes, but then I couldn't figure out how two map the new methods. Should I keep the original annotations at VehicleInstance? Should both of them point to VEHICLE_ID? Every combination I tried seemed to fail.
So in conclusion - How can I map VehicleInstance, CarInstance and TruckInstance so that I can select in HQL a TruckInstance based on its Height property?
Thanks in advance!

Categories

Resources