I am having some problems with Hibernate and the oneToMany
mapping.
Here is my function:
Location location = new Location(); location.setDateTime(new Date()); location.setLatitude(lat); location.setLongitude(lon); location = this.locationDao.save(location); merchant = new Merchant(); merchant.setAddress(address); merchant.setCity(city); merchant.setCountry(country); merchant.setLocation(location); merchant.setName(name); merchant.setOrganization(organization); merchant.setPublicId(publicId); merchant.setZipCode(zipCode); merchant.setApplication(this.applicationDAO.findByPublicId(applicationPublicId)); merchant = this.merchantDao.save(merchant); return merchant;
Here are my two entities:
Location
import java.io.Serializable; import java.util.Date; import java.util.List; import javax.persistence.*; import javax.validation.constraints.NotNull; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; @Entity @Table(name = "location") @XmlRootElement public class Location implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Basic(optional = false) @Column(name = "id", nullable = false) private Long id; @Basic(optional = false) @NotNull @Column(name = "latitude", nullable = false) private double latitude; @Basic(optional = false) @NotNull @Column(name = "longitude", nullable = false) private double longitude; @Basic(optional = false) @NotNull @Column(name = "date_time", nullable = false) @Temporal(TemporalType.TIMESTAMP) private Date dateTime; @OneToMany(cascade = CascadeType.ALL, mappedBy = "location") private List<Merchant> retailerList; @OneToMany(cascade = CascadeType.ALL, mappedBy = "location") private List<MobileUser> userList; public Location() { } public Location(Long id) { this.id = id; } public Location(Long id, double latitude, double longitude, Date dateTime) { this.id = id; this.latitude = latitude; this.longitude = longitude; this.dateTime = dateTime; } public Long getId() { return id; } //getters and setters @XmlTransient public List<Merchant> getRetailerList() { return retailerList; } public void setRetailerList(List<Merchant> retailerList) { this.retailerList = retailerList; } @XmlTransient public List<MobileUser> getUserList() { return userList; } public void setUserList(List<MobileUser> userList) { this.userList = userList; } @Override public int hashCode() { int hash = 0; hash += (id != null ? id.hashCode() : 0); return hash; } @Override public boolean equals(Object object) { // TODO: Warning - this method won't work in the case the id fields are not set if (!(object instanceof Location)) { return false; } Location other = (Location) object; if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { return false; } return true; } @Override public String toString() { return "com.fgsecure.geoloc.entities.Location[ id=" + id + " ]"; }
Merchant
import java.io.Serializable; import javax.persistence.*; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import javax.xml.bind.annotation.XmlRootElement; import org.codehaus.jackson.annotate.JsonAutoDetect; import org.codehaus.jackson.annotate.JsonIgnore; @JsonAutoDetect @Entity @Table(name = "retailer") @XmlRootElement public class Merchant implements Serializable { private static final long serialVersionUID = 1L; @JsonIgnore @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Basic(optional = false) @Column(name = "id", nullable = false) private Long id; @Basic(optional = false) @NotNull @Size(min = 1, max = 50) @Column(name = "public_id", nullable = false, length = 50) private String publicId; @Basic(optional = false) @NotNull @Size(min = 1, max = 50) @Column(name = "name", nullable = false, length = 50) private String name; @Size(max = 50) @Column(name = "organization", length = 50) private String organization; @Size(max = 128) @Column(name = "address", length = 128) private String address; @Size(max = 10) @Column(name = "zip_code", length = 10) private String zipCode; @Size(max = 50) @Column(name = "city", length = 50) private String city; @Size(max = 50) @Column(name = "country", length = 50) private String country; @JoinColumn(name = "location_id", referencedColumnName = "id", nullable = false) @ManyToOne(optional = false) private Location location; @JoinColumn(name = "application_id", referencedColumnName = "id", nullable = false) @ManyToOne(optional = false) private Application application; public Merchant() { } public Merchant(Long id) { this.id = id; } public Merchant(Long id, String publicId, String name) { this.id = id; this.publicId = publicId; this.name = name; } //getters and setters @Override public int hashCode() { int hash = 0; hash += (id != null ? id.hashCode() : 0); return hash; } @Override public boolean equals(Object object) { // TODO: Warning - this method won't work in the case the id fields are not set if (!(object instanceof Merchant)) { return false; } Merchant other = (Merchant) object; if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) { return false; } return true; } @Override public String toString() { return "com.fgsecure.geoloc.entities.Retailer[ id=" + id + " ]"; } }
And each time I am calling my function I get:
org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save():
for this line:
location = this.locationDao.save(location);
I don't understand why. Because in that case there is no need to manually assigne the id of location as it is auto generated. I must have done something wrong but after 3 days looking I don't find.
I am using PostGreSQL and the id is an autogenerated ID with this sequence:
nextval('location_id_seq'::regclass)`
EDIT SOLVE:
Ok Thanks for your answers.
If it can help other person in the future, just need to modify the param of the id by:
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Basic(optional = false) @Column(name = "id",unique=true, nullable = false)