Reputation: 23
I've just recently started to wet my feet on hibernate. I've been following an online hibernate tutorial on hibernate. In the lesson, two classes were created; UserDetails, Address. The UserDetails class uses the @Entity annotation while the Address class uses the @Embeddable annotation.
Rather than creating the primary key, "ADDRESS_ID", using the @GenericGenerator and @CollectionId annotations in the UserDetails class, wouldn't it be simpler and more practical to just declare an instance variable (private int ADDRESS_ID) in the Address class, and use the @Id @GeneratedValue annotations to make the variable a primary key of the USER_ADDRESS table?
Thanks
UserDetails.java
package dto;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;
@Entity
public class UserDetails {
@Id
@Column
private int userId;
@Column
private String userName;
@ElementCollection
@JoinTable(name="USER_ADDRESS", joinColumns=@JoinColumn(name="USER_ID"))
@GenericGenerator(name = "sequence-gen", strategy = "sequence")
@CollectionId(columns = { @Column(name="ADDRESS_ID") }, generator = "sequence-gen", type = @Type(type="long"))
private Collection<Address> listOfAddresses = new ArrayList<Address>();
public Collection<Address> getListOfAddresses() {
return listOfAddresses;
}
public void setListOfAddresses(Collection<Address> listOfAddresses) {
this.listOfAddresses = listOfAddresses;
}
public Date getJoinedDate() {
return joinedDate;
}
public void setJoinedDate(Date joinedDate) {
this.joinedDate = joinedDate;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
Address.java
package dto;
import javax.persistence.Column;
import javax.persistence.Embeddable;
@Embeddable
public class Address {
@Column(name="STREET_NAME")
private String street;
@Column(name="CITY_NAME")
private String city;
@Column(name="STATE_NAME")
private String state;
@Column(name="PIN_CODE")
private String pincode;
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getPincode() {
return pincode;
}
public void setPincode(String pincode) {
this.pincode = pincode;
}
}
Upvotes: 2
Views: 3318
Reputation: 32145
Actually there's no need for an Id
attribute in an embeddable type (referred to as Component in Hibernate), because they're as they're just a composition of values and they don't support shared references, so even if two Objects contains the same Component values they won't be the same reference but only two objects that has the same values, you can see it from the Hibernate Component Mapping:
Like value types, components do not support shared references. In other words, two persons could have the same name, but the two person objects would contain two independent name objects that were only "the same" by value. The null value semantics of a component are ad hoc. When reloading the containing object, Hibernate will assume that if all component columns are null, then the entire component is null. This is suitable for most purposes.
So basically there's no need for an Id
attribute here.
But to answer your question on which approach is better?
I think they do quite the same thing but using @Id
and @GeneratedValue
in your Address
Entity would be much simpler as you said and most important is that it will be much practical because you don't have to redefine this using @CollectionId
in each Entity that contains your Adress
component, so you will have less and cleaner code in your project.
So using @Id
in your Adress
Entity will be the best way to go with in order of performance
, readability
and maintainability
.
Upvotes: 1
Reputation: 743
An embeddable type is a value type you may also find the term : Component. these objects are not entities but just part of an entity which means that their lifecycle is bound to an entity.
As per the hibernate doc
embeddable types do not have any identity, being managed by their owning entity.
The way you proceed seems to be the good practice.
Upvotes: 0