2013-04-22 9 views
28

Sto riscontrando alcuni problemi con Hibernate e la mappatura oneToMany.Ibernazione: gli ID per questa classe devono essere assegnati manualmente prima di chiamare save()

Qui è la mia funzione:

 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; 

Qui sono i miei due entità:

Posizione

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 + " ]"; 
    } 
} 
.210

E ogni volta che io chiamo la mia funzione ottengo:

org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): 

per questa linea:

location = this.locationDao.save(location); 

Non capisco perché. Perché in questo caso non è necessario assegnare manualmente l'ID della posizione in quanto viene generato automaticamente. Devo aver fatto qualcosa di sbagliato ma dopo 3 giorni di ricerca non trovo.

Sto usando PostgreSQL e l'ID è un ID generato automaticamente con questa sequenza:

nextval('location_id_seq'::regclass)` 

EDIT SOLVE:

Grazie Ok per le vostre risposte.

Se può aiutare altre persone in futuro, solo bisogno di modificare il parametro della id da:

@Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = "id",unique=true, nullable = false) 
+0

quale database si sta utilizzando – PSR

+0

mercante funziona correttamente per u – PSR

+0

tenta di modificare id nome algoritmo ad un altro per testare – PSR

risposta

18

l'attributo id non è impostato. questo potrebbe essere dovuto al fatto che il campo DB non è impostato su incremento automatico? che DB stai usando? MySQL? il tuo campo è impostato su AUTO INCREMENT?

+0

Grazie per aver risposto. Sto usando PostGre con id autogenerato. Ho appena modificato il mio post. – Boris

+6

per MySQL e AI, funziona. potresti voler controllare se questo è anche il caso di postgresql. i miei POJO sembrano più o meno sempre così: \t @Id \t @GeneratedValue (strategia = GenerationType.IDENTITY) @Column (name = "id", unico nel suo genere = true, nullable = false) pubblico lungo getId() { ritorno this.id; } – rmalchow

+0

Ok grazie mille. Sembra che mancasse semplicemente il unique = true ... – Boris

Problemi correlati