Home > OS >  "org.hibernate.PersistentObjectException: detached entity passed to persist" error that I
"org.hibernate.PersistentObjectException: detached entity passed to persist" error that I

Time:05-18

I've recently started working with JPA and Hibernate for a school project, and it basically stores continents, countries and cities in a database.

When trying to use the persist method on an entity, I get the error mentioned in the title.

Whichever threads I've visited tackle a lot more complex problems, and don't really help my case. I'm hoping to find some guidance by posting here.

This is the database creation script. It's a PostgreSQL database.

create table continents(
    id integer primary key,
    name varchar
);
create table countries(
    id integer primary key,
    name varchar,
    code varchar,
    continent_ID integer,
    constraint fk_continents
                      foreign key (continent_ID)
                      references continents(id)
);
create table cities(
    id integer primary key,
    country_ID integer,
    name varchar,
    hasCapital boolean,
    latitude float,
    longitude float,
    constraint fk_countries
    foreign key (country_ID)
    references countries(id)
);

Basically, the countries table uses the continents table's ID as a foreign key, and the cities table uses the countries table's ID again, as a foreign key.

The error I get is caused by me trying to persist a new continent entity. This is the code that gets executed:

public static void main(String[] args) {
        EntityManagerFactory ef = Persistence.createEntityManagerFactory("default");
        EntityManager em = ef.createEntityManager();
        EntityTransaction transaction = em.getTransaction();
        try{
            transaction.begin();
            ContinentsEntity continentEntity = new ContinentsEntity();

            continentEntity.setId(1);
            continentEntity.setName("Europe");
            em.persist(continentEntity);


            transaction.commit();
        } finally {
            if(transaction.isActive()){
                transaction.rollback();
            }
            em.close();
            ef.close();
        }
    }

All the entity classes are generated by Intellij, through the persistence tool.

Here are the classes.

ContinentsEntity:

package entity;

import javax.persistence.*;

@Entity
@Table(name = "continents", schema = "public", catalog = "postgres")
public class ContinentsEntity {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(name = "id")
    private int id;
    @Basic
    @Column(name = "name")
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        ContinentsEntity that = (ContinentsEntity) o;

        if (id != that.id) return false;
        if (name != null ? !name.equals(that.name) : that.name != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result   (name != null ? name.hashCode() : 0);
        return result;
    }
}

CountriesEntity:

package entity;

import javax.persistence.*;

@Entity
@Table(name = "countries", schema = "public", catalog = "postgres")
public class CountriesEntity {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(name = "id")
    private int id;
    @Basic
    @Column(name = "name")
    private String name;
    @Basic
    @Column(name = "code")
    private String code;
    @Basic
    @Column(name = "continent_id")
    private Integer continentId;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public Integer getContinentId() {
        return continentId;
    }

    public void setContinentId(Integer continentId) {
        this.continentId = continentId;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        CountriesEntity that = (CountriesEntity) o;

        if (id != that.id) return false;
        if (name != null ? !name.equals(that.name) : that.name != null) return false;
        if (code != null ? !code.equals(that.code) : that.code != null) return false;
        if (continentId != null ? !continentId.equals(that.continentId) : that.continentId != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result   (name != null ? name.hashCode() : 0);
        result = 31 * result   (code != null ? code.hashCode() : 0);
        result = 31 * result   (continentId != null ? continentId.hashCode() : 0);
        return result;
    }
}

CitiesEntity:

package entity;

import javax.persistence.*;

@Entity
@Table(name = "cities", schema = "public", catalog = "postgres")
public class CitiesEntity {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(name = "id")
    private int id;
    @Basic
    @Column(name = "country_id")
    private Integer countryId;
    @Basic
    @Column(name = "name")
    private String name;
    @Basic
    @Column(name = "hascapital")
    private Boolean hascapital;
    @Basic
    @Column(name = "latitude")
    private Double latitude;
    @Basic
    @Column(name = "longitude")
    private Double longitude;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Integer getCountryId() {
        return countryId;
    }

    public void setCountryId(Integer countryId) {
        this.countryId = countryId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Boolean getHascapital() {
        return hascapital;
    }

    public void setHascapital(Boolean hascapital) {
        this.hascapital = hascapital;
    }

    public Double getLatitude() {
        return latitude;
    }

    public void setLatitude(Double latitude) {
        this.latitude = latitude;
    }

    public Double getLongitude() {
        return longitude;
    }

    public void setLongitude(Double longitude) {
        this.longitude = longitude;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        CitiesEntity that = (CitiesEntity) o;

        if (id != that.id) return false;
        if (countryId != null ? !countryId.equals(that.countryId) : that.countryId != null) return false;
        if (name != null ? !name.equals(that.name) : that.name != null) return false;
        if (hascapital != null ? !hascapital.equals(that.hascapital) : that.hascapital != null) return false;
        if (latitude != null ? !latitude.equals(that.latitude) : that.latitude != null) return false;
        if (longitude != null ? !longitude.equals(that.longitude) : that.longitude != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result   (countryId != null ? countryId.hashCode() : 0);
        result = 31 * result   (name != null ? name.hashCode() : 0);
        result = 31 * result   (hascapital != null ? hascapital.hashCode() : 0);
        result = 31 * result   (latitude != null ? latitude.hashCode() : 0);
        result = 31 * result   (longitude != null ? longitude.hashCode() : 0);
        return result;
    }
}

It might be something with my DB design, or the way Intellij generated my entity classes, but I just can't figure it out.

EDIT: My DB design was the fault, as well as me trying to persist the id. I modified all pk's to be serial, as well as removing the line of code where I added the id, and that did the trick.

CodePudding user response:

The problem is, that you're trying to persist an entity with id being set and Hibernate thinks it's an existing entity, but can't find it in it's Persistence Context. Try to persist the entity without the ID, it should be generated automatically.

  • Related