Reputation: 5624
I have one very important table in my project - Mandatory table. It has a few column but in this case the most important is the primary key.
Mandatory
1. id (Long Primary Key)
...
Now I have to add tow new tables - Additional table, and Extra table. Both of them have only two columns. In Additional both are primary key. One of them are also foreign key as you can see.
Additional
1. mandatory_id (Long Primary Key FK -> Mandatory.id)
2. description (Varchar(512) Primary Key)
In Extra table primary key is also foreign key.
Extra
1. mandatory_id (Long Primary Key FK -> Mandatory.id)
2. text (Varchar(512)
I am considering how can I implement it in my project using Hibernate.
I have declared them in this way (here without getters, setter and etc), MandatoryEntity
class:
@Entity
@Table(name = "mandatory")
public class MandatoryEntity {
@OneToMany
@JoinColumn(name = "mandatory_id")
protected List<AdditionalEntity> additonals;
@OneToOne
@JoinColumn(name = "mandatory_id")
protected ExtraEntity extra;
}
AdditionalEntity
class:
@Entity
@Table(name = "additional")
public class AdditionalEntity {
@EmbeddedId
private AdditionalPK id;
@ManyToOne(fetch = FetchType.LAZY)
@Fetch(value = FetchMode.JOIN)
@JoinColumn(name = "mandatory_id", nullable = false, insertable = false, updatable = false)
protected MandatoryEntity mandatory;
}
AdditionalPK
class:
@Embeddable
public class AdditionalPK {
@Column(name = "mandatory_id")
private Long mandatoryId;
@Column(name = "description")
private String description;
}
ExtraEntity
class:
@Entity
@Table(name = "extra")
public class ExtraEntity {
@Id
@Column(name = "mandatory_id")
private Long id;
@OneToOne
@PrimaryKeyJoinColumn
protected MandatoryEntity mandatory
@Column(name = "text")
protected String text;
}
At this moment the laptop on which I am working is broken so I have time to my considerations. I have found in JPA Specification @SecondaryTables
annotation. May I use this annotation in my case? These are only two tables, each of them has only two columns. The first has composite primary key, the second not.
Maybe there is another way to implement this tables in one MandatoryEntity
? Without two new entities: AdditionalEntity
and ExtraEntity
?
Upvotes: 1
Views: 223
Reputation: 2112
First of all, let me rephrase what I understood from your requirements.
You have two other entities that specify additional information to the Mandatory entity. Of which
a. Multiple Additional information can be specified (ManyToOne)
b. One Extra information can be specified (OneToOne)
Generally this is quite a basic usecase. One thing you have to decide here is whether you need bidirectional mapping or if unidirectional mapping (access only via Mandatory entity) suffices. I expect unidirectional mapping to be a good choice for your usecase since it seems that Mandatory is your root entity. In your code you tried to model a bidirectional relation but forgot to specify the inverse. This will actually result in two independent relations. You should specify the target of a bidirectional relation like this:
@Entity
@Table(name = "mandatory")
public class MandatoryEntity {
// you need a mapped by to mark the relation as bidirectional
@OneToMany(mappedBy = "mandatory")
protected List additonals;
@OneToOne
protected ExtraEntity extra;
}
@Entity
@Table(name = "additional")
public class AdditionalEntity {
@EmbeddedId
private AdditionalPK id;
@ManyToOne(fetch = FetchType.LAZY)
protected MandatoryEntity mandatory;
}
You also specified a lot of additional mapping information that is not needed in your example which makes everything seem way too complex. Also Why are you using an embedded key? I think an auto-generated key would work for you as well. My suggestion for your model would be as follows:
@Entity
@Table(name = "mandatory")
public class MandatoryEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// you need a mapped by to mark the relation as bidirectional
@OneToMany(mappedBy = "mandatory")
protected List additonals;
@OneToOne
protected ExtraEntity extra;
}
@Entity
@Table(name = "additional")
public class AdditionalEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
protected MandatoryEntity mandatory;
}
@Entity
@Table(name = "extra")
public class ExtraEntity {
// you might also not use auto-value here and set the id to the id of the owning
// mandatory entity
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "text")
protected String text;
}
If I am missing some requirements and my proposed mapping does not work in your case, then please add more information about your requirements and we can discuss this further.
Upvotes: 1