Delete Inherited class JPA - java

I have a table defined as this:
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name = "EVENT_TYPE")
public abstract class Event implements Serializable {
#Id
#GeneratedValue
private Long id;
...
}
Then I have this inherited tables:
#Entity
#DiscriminatorValue("BOOLEANVALUE")
public class BooleanValueEvent extends Event {
...
}
#Entity
#DiscriminatorValue("EXACTVALUE")
public class ExactValueEvent extends Event {
...
}
Hibernate creates two table in database, but when I try to delete on JPA an inherited object it returns foreign key constraint violation error, because It try to delete first Event class. How can I delete inherited class first when I delete superClass in order to avoid key constraint violation error?
Thank you.

Using cascade delete , removing a SubTable entity will succeed and it will remove both the subTable and the parentTable rows.
#Entity
#DiscriminatorValue("BOOLEANVALUE")
#OnDelete(action = OnDeleteAction.CASCADE)
public class BooleanValueEvent extends Event {
...
}
#Entity
#DiscriminatorValue("EXACTVALUE")
#OnDelete(action = OnDeleteAction.CASCADE)
public class ExactValueEvent extends Event {
...
}

Finally I solved it with.
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "typeName")
#JsonSubTypes({
#Type(value = BooleanValueEvent.class),
#Type(value = ExactValueEvent.class)
})
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name = "EVENT_TYPE")
public abstract class Event implements Cloneable, Serializable {
#Id
#GeneratedValue
private Long id;
...
}
And
#Entity
#DiscriminatorValue("BOOLEANVALUE")
public class BooleanValueEvent extends Event {
...
}
#Entity
#DiscriminatorValue("EXACTVALUE")
public class ExactValueEvent extends Event {
...
}

Related

Fail to map by MappedSuperclass's attribute

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 {}

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

Mapping AbstractEntity to SubClassDTO - Single Table Strategy

I'm trying to mapp Entity (TrainingEntity) to DTO, where one of the fields is a Set with ManyToMany reference to an AbstractEntity (CoachEntity) divided by Single Table into two subclasses: ExternalCoach and InternalCoach.
Both subclasses have different data, therefore require two different mappers.
#Entity
#Table(name = "TRAINING")
public class TrainingEntity extends AbstractEntity {
#ManyToMany()
#JoinTable(name = "TRAINING_EMPLOYEE", joinColumns = { #JoinColumn(name = "TRAINING_ID") }, inverseJoinColumns = {
#JoinColumn(name = "COACH_ID") })
private Set<CoachEntity> coachEntities;
#Column(nullable = false)
private TrainingType trainingType;
......some data....
}
Abstract Coach Entity
#Entity
#Table(name = "COACH")
#DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class CoachEntity extends AbstractEntity {
......some data....
}
Coach Subclasses:
#Entity
#DiscriminatorValue("EXTERNAL")
public class ExternalCoachEntity extends CoachEntity {
......some data....
}
#Entity
#DiscriminatorValue("INTERNAL")
public class InternalCoachEntity extends CoachEntity {
......some data....
}
One mapper for Abstract Coach class won't have acces to subclasses methods and fields, so I need two different for External and Internal. Than I would have to use them in TrainingMapper class, but (example of internal):
public class CustomTrainingMapper {
public static TrainingDto toTrainingDto(TrainingEntity trainingEntity){
if(trainingEntity == null){
return null;
}
if(trainingEntity.getTrainingType().equals(TrainingType.INTERNAL)){
Set<CoachEntity> coachEntities = trainingEntity.getCoachEntities();
Set<CoachDto> coachDtos = CustomInternalCoachMapper.toDTOSet((Set<InternalCoachEntity>)coachEntities);
}
I get:
cannot cast from Set<CoachEntity> to Set<InternalCoachEntity>
Without cast it simply doesn't see mappers methods with subclass input.
The method toDTOSet(Set<InternalCoachEntity>) in the type CustomInternalCoachMapper is not applicable for the arguments (Set<CoachEntity>)
When in mapper I change method input to abstract Coach Class it doesn't see subclasses methods and fields.
Part of InternalMapper:
public class CustomInternalCoachMapper {
public static CoachDto toCoachDto(InternalCoachEntity coachEntity) {
if (coachEntity == null) {
return null;
}
EmployeeDto employeeDto = CustomEmployeeMapper.toEmployeeDto(coachEntity.getEmployeeEntity());
return new InternalCoachDto(coachEntity.getId(), coachEntity.getVersion(), coachEntity.getCreateDate(),
coachEntity.getUpdateDate(), coachEntity.getName(), coachEntity.getSurname(), employeeDto);
}
Is it possible to mapp this AbstractEntity Set into subclasses DTOs?
I also tried with AbstractDto for Coaches, but then I'm facing the same problem with no access to subclasses getters and setters.

How to avoid duplicate code in JPA Entity

I have 2 Object A and B, which have same attributes, but different table.
#Entity
#Table(name = "A")
public class A {
#Id
private Integer id;
...
}
and
#Entity
#Table(name = "B")
public class B {
#Id
private Integer id;
...
}
it will cause duplicate code because every attributes are same.
What is best practice to do this kind of problem?
I'd create a #MappedSupperclass for this, and extend from it. It would look like this
#MappedSuperclass
public class Common {
#Id
private Integer id;
}
#Entity
#Table(name = "A")
public class A extends Common {
...
}
#Entity
#Table(name = "B")
public class B extends Common {
...
}
This doesn't create an entity hierarchy, but only moves common entity attributes in a super class. Often used for id, version, createdBy etc.

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