65

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)
Draken
  • 3,134
  • 13
  • 34
  • 54
Boris
  • 653
  • 1
  • 5
  • 6

3 Answers3

38

your id attribute is not set. this MAY be due to the fact that the DB field is not set to auto increment? what DB are you using? MySQL? is your field set to AUTO INCREMENT?

rmalchow
  • 2,689
  • 18
  • 31
  • Thanks for answering. I am using PostGre with autogenerated id. I just edited my post. – Boris Apr 22 '13 at 08:05
  • 11
    for MySQL and AI, this works. you might want to check if that's also the case with postgresql. my pojos pretty much always look like this: @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="id", unique=true, nullable=false) public Long getId() { return this.id; } – rmalchow Apr 22 '13 at 08:08
  • in oracle this may cause due to sequence name – dom Jan 29 '17 at 11:29
10

Assign primary key in hibernate

Make sure that the attribute is primary key and Auto Incrementable in the database. Then map it into the data class with the annotation with @GeneratedValue annotation using IDENTITY.

@Entity
@Table(name = "client")
data class Client(
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id") 
    private val id: Int? = null
)

GL

Source

Jeroen Steenbeeke
  • 3,884
  • 5
  • 17
  • 26
Braian Coronel
  • 22,105
  • 4
  • 57
  • 62
  • it worked for me, but why do I need to add `@GeneratedValue`, if the table was already created in the db before, I believe that this annotation works on generating the table schema, and after that, it will not affect anything if I removed it. @BraianCoronel – Mohammed Nosirat Apr 28 '23 at 14:39
0

1. Identify the name of the sequences created in your database schema

SELECT sequence_schema, sequence_name FROM information_schema.sequences ORDER BY sequence_name;

2. Make sure the sequence name matches the associated name in the entity

public class Calmicprsusc {
    private static final long serialVersionUID = 1L;

    @GenericGenerator(
            name = "calmicprsuscGen",
            strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
            parameters = {
                    @org.hibernate.annotations.Parameter(name = "sequence_name", value = "calmicprsusc_idcalmicprsusc_seq"),
                    @org.hibernate.annotations.Parameter(name = "initial_value", value = "1"),
                    @org.hibernate.annotations.Parameter(name = "increment_size", value = "1")}
    )

    @Id
    @GeneratedValue(strategy= GenerationType.SEQUENCE, generator="calmicprsuscGen")
    @Column(name = "idcalmicprsusc")
    private Integer idcalmicprsusc;  

    @Column(name = "idsample")
    private Integer idsample; 
}
Krishna Majgaonkar
  • 1,532
  • 14
  • 25