Reputation: 3496
Here's the problem which I can't find a solution for and, I guess, it is either impossible or I am heading wrong direction with the whole idea.
Initially part of my JPA hierarchy was like so:
@MappedSuperclass
public abstract class AbstractEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
protected Long id;
.....
}
@Audited
@Entity
@Table(name = "T_MEETING")
public class Meeting extends AbstractEntity implements Groupable {...}
@Audited
@Entity
@Table(name = "T_QUESTION")
public class Question extends AbstractEntity implements Groupable {...}
This database has been used for some time until need for custom fields in some object arose.
I decided to go follwing route - stuck an abstract entity as a base for objects with custom fields:
@Audited
@Entity
@Table(name = "T_CF_OBJECT")
@Inheritance(strategy = InheritanceType.JOINED)
@PrimaryKeyJoinColumn(name = "ID", referencedColumnName = "CF_OBJECT_ID")
public abstract class EntityWithCustomFields extends AbstractEntity {...}
@Audited
@Entity
@Table(name = "T_QUESTION")
public class Question extends EntityWithCustomFields implements Groupable {...}
@Audited
@Entity
@Table(name = "T_MEETING")
public class Meeting extends EntityWithCustomFields implements Groupable {...}
I had tried different options and there's always a problem:
JPA provider (hibernate in my case), I guess, inserts parent first and hence its CF_OBJECT_ID
is null
Hibernate: insert into t_cf_object (id, cf_object_id) values (null, ?) Hibernate: insert into t_meeting (active, date, c_group, last_notification_date, only_for_members, place, questions_order, subject, update_date, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
If I omit @PrimaryKeyJoinColumn
annotation on the base entity, then its Id
and Id
s of the descendants are used as the join column and what it leads to is subclass tables do not have the same id. Which is good at the start, but we already have tons of records in both tables and they have the same value in the id
column. It is not an option to change id
s in the tables.
What is the correct way to use inheritance in my case, so it gets in as seamlessly as possible ? Would be nice to find out how do I make hibernate persist subclass instance first and then pass its id to the persisted superclass. There's gotta be annotation for that, right ?
Edit: As for suggestion to use @MappedSuperclass
I can't really use a @MappedSuperClass
for the following reason. The parent class EntityWithCustomFields
is used to refer to by the ManyToOne
relationship from the CustomFieldValue
class. In the code it would look like follows:
@Entity
@Audited
@Table(name = "T_CF_VALUES")
public class CustomFieldValue extends AbstractEntity {
@ManyToOne
@JoinColumn(name = "customFieldObject", nullable = false)
private EntityWithCustomFields customFieldObject;
....
}
@Audited
@Entity
@Table(name = "T_CF_OBJECT")
@Inheritance(strategy = InheritanceType.JOINED)
@PrimaryKeyJoinColumn(name = "ID", referencedColumnName = "CF_OBJECT_ID")
public abstract class EntityWithCustomFields extends AbstractEntity {
@OneToMany(fetch = FetchType.LAZY, mappedBy = "customFieldObject", cascade = CascadeType.ALL)
private List<CustomFieldValue> customFields;
....
}
I don't think @MappedSuperclass
can be used in this sort of stuff.
Upvotes: 1
Views: 823
Reputation: 691715
It seems to me that you don't want entity inheritance here, but an additional mapped superclass for your entities with custom fields.
Entity inheritance must be used when you have a real is-a functional relationship. For example, an invoice might have a list of products, and the product entity would be the root of an inheritance tree (Vegetable, Meat, Clothe, etc.). And in this case, a Vegetable is a product, and of course two products may not have the same ID, because a Price entity for example could reference a Product via a foreign key, and if two products had the same ID, it wouldn't work at all.
In your case, the entities with custom fields are completely unrelated. They just happen to have common fields and you want to factor this by putting these common fields in a superclass. That's what MappSuperclass is for. And those custom fields should be duplicated in each and every entity table. This will, anyway, be much more efficient than a joined inheritance (which leads to more queries, and more complex and hard to optimize queries).
Upvotes: 0