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.
Related
I have two tables A and B:
#Entity
public class A {
}
#Entity
public class B {
private final A a;
private String someBSpecificField;
}
Entity A is already Coded nicely and mapped to an existing table. My job is to create B and for some reason I prefer composition over inheritance between A and B. At the same time I want to have single table for A and B to avoid joins when reading. Can I do like this:
#Entity
#Table(name = "a")
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorColumn(name = "a_type_enum", discriminatorType =
DiscriminatorType.INTEGER)
#DiscriminatorValue("100")
public class A {
}
#Entity
#Table(name = "a")
#DiscriminatorValue("500")
public class B {
private final A a;
private String someBSpecificField;
}
If the type is a complex object then you need to annotate that type with #Embeddable and use it in your #Entity class.
if you want to override the attribute names for your #Embeddable class so they have different column names, you can do so with the #AttributeOverrides annotation.
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 {
...
}
I'm trying to create a way to model my future aplications using an AbstractEntity
My problem now is the Sequence type for Postgres
In my abstract class I don't now how generate one sequence per entity class
It is possible?
Abstract
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Abstract {
#Id
#GeneratedValue(generator="seq_Broker",strategy=GenerationType.SEQUENCE)
#SequenceGenerator(name="seq_Broker",sequenceName="seq_Broker")
private Long id;
}
EntityModel
#Entity
#Table(name = "tb_EntityModel")
public class EntityModel extends Abstract{
private String value;
private String value2;
public EntityModel(String value, String value2) {
this.value = value;
this.value2 = value2;
}
}
It is not possible with an #Entity superclass for any inheritance types, as the master table (the table for Abstract) will always contain the used ids - and it is obvious that you can only use one sequence for that, as otherwise you would have a problem with uniqueness.
But you can define #MappedSuperclass for Abstract:
#MappedSuperclass
public abstract class Abstract {
public static final String SEQUENCE_GENERATOR = "seq";
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE_GENERATOR)
private Long id;
}
#Entity
#Table(name = "tb_EntityModel")
#SequenceGenerator(name = Abstract.SEQUENCE_GENERATOR, sequenceName = "tb_entity_sequence")
public class EntityModel extends Abstract {
...
}
I am working on JPA project and I need your help.
I have two classes, “Person” and “Leader” which inherits from Person.
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(unique = true)
private String personId;
}
And
#Entity
public class Leader extends Person implements Serializable {
private List < Person > listTeam;
public void addPersonInTeam(Person e) {
listTeam.add(e);
}
}
My question Is, do I need to have JPA annotations #OneToMany or something else before private List listTeam in class Leader?
Thank you very much
You need to specify a mapping between the two classes because for Hibernate the association is not relevant here, you have to use annotations in both sides and I guess you will need a OneToMany mapping here :
Here's the mapping that you are seraching for:
In Person class:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(unique = true)
private String personId;
#ManyToOne
#JoinColumn(name="leader_id")
private Leader leader;
//getter and setter
}
In Leader class:
#Entity
public class Leader extends Person implements Serializable {
#OneToMany(mappedBy = "leader")
private List <Person> listTeam;
//getter and setter
public void addPersonInTeam(Person e) {
listTeam.add(e);
}
}
For further information you can see these links:
Hibernate – One-to-Many example (Annotation).
Hibernate One To Many Annotation tutorial.
Note:
I don't see the use of the field personId in the Person class, there's no need to use two differents ids.
EDIT:
To answer your questions:
The #JoinColumn(name="leader_id") is not mandatory, but it's used to specify the foreign key name.
If the relation is ManyToMany the mappedBy property is used to specify the owner of the relationship, you can see this answer for more details.
I have two entity-classes A and B. For A there is only one instance of class B. Through a lifecicle of application I need to create new instnace of B for A. But for history log I need to store previous instance of B with links to an this A instance. So I created next mapping:
#Entity
class A {
#OneToOne
#JoinColumn(name="B_ID")
B b;
}
#Entity
class B {
#OneToOne
#JoinColumn(name="A_ID")
A a;
}
///////
CREATE TABLE A_TABLE (ID uuid, B_ID uuid, FOREIGN KEY (B_ID) REFERENCES B_TABLE(ID));
CREATE TABLE B_TABLE (ID uuid, A_ID uuid, FOREIGN KEY (A_ID) REFERENCES A_TABLE(ID));
I already have some correct data in my tables, but each time, when I trying to get any instance of A class, the b field is null. So, what am I doing wrong?
UPD_0
Ok, here what I'm realy dealing with:
#MappedSuperclass
public abstract class BaseUuidEntity {
#Id
#Column(name = "ID")
#Persistent
protected UUID id;
}
#MappedSuperclass
public class StandartEntity extends BaseUuidEntity { ... }
#MappedSuperclass
public abstract class AbstractEntity extends BaseUuidEntity { ... }
#Entity(name = "CardEntity")
#Table(name = "TBL_CARD")
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name = "CARD_TYPE", discriminatorType = DiscriminatorType.INTEGER)
#DiscriminatorValue("0")
public class CardEntity extends AbstractEntity { ... }
#Entity("aEntity")
#DiscriminatorValue("1")
#Table(name = "A_TABLE")
class A extends CardEntity {
#OneToOne
#JoinColumn(name="B_ID")
B b;
public String getBName() {
return b.getName(); // NullPointerException
}
}
#Entity("bEntity")
#Table(name = "B_TABLE")
class B extends StandartEntity {
#Column(name="name")
String name;
public String getName() {
return this.name;
}
}
-- A_TABLE (ID, B_ID)
'41a2647d-2ef6-f507-92ee-bff0f784b6f3', '5d3c66da-b377-11e4-bc9c-1008b124eacf'
-- B_TABLE (ID, A_TABLE, NAME)
'5d3c66da-b377-11e4-bc9c-1008b124eacf', '41a2647d-2ef6-f507-92ee-bff0f784b6f3', 'Some text'
I'm getting all A entities (in my case - it's one)
select e from aEntity e
and trying to get name of b entity in each of them, but getting nullpointer, cause b is null;
I'm not sure if it will make any difference, but try changing the code in getBName() to use the getter instead of directly referencing the instance variable b:
public String getBName() {
return getB().getName();
}
instead of:
public String getBName() {
return b.getName(); // NullPointerException
}
I suspect that this could be the issue because JPA implementations create proxies for entities, which are usually subclasses of your entities, and these proxies override your getters and setters. So if you don't use the getter it could be that the instance variable does not get initialized properly.
you need mappedBy anotation: http://en.wikibooks.org/wiki/Java_Persistence/OneToOne
to inform java who is in charge of this relationship and when the 'foreign'id' is storred. You also need the foreign key in only one of the entities not both!