"org.hibernate.PersistentObjectException: detached entity passed to persist" 这个错误让我无法理解。

3
我最近为一个学校项目开始使用JPA和Hibernate,它基本上将大陆、国家和城市存储在数据库中。
当尝试在实体上使用persist方法时,我会遇到标题中提到的错误。
无论我访问哪个线程,都会处理更复杂的问题,对我的情况没有太大帮助。我希望通过在这里发布来寻找一些指导。
这是数据库创建脚本。它是一个PostgreSQL数据库。
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)
);

基本上,countries表将continents表的ID作为外键使用,而cities表再次使用countries表的ID作为外键。

我遇到的错误是由于我试图持久化一个新的continent实体引起的。这是执行的代码:

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();
        }
    }

所有实体类都是通过Intellij的持久化工具生成的。
以下是这些类:
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;
    }
}

可能是我的数据库设计有问题,或者是Intellij生成实体类的方式有问题,但我无法弄清楚。

编辑:我的数据库设计有问题,还有我试图持久化ID。我将所有主键修改为序列,并删除了添加ID的代码行,这样就解决了问题。

3个回答

8
问题在于你试图持久化一个已经设置了ID的实体,而Hibernate认为这是一个已存在的实体,但是在其持久化上下文中找不到它。尝试不带ID持久化实体,它应该会自动生成。

谢谢你的回答!我修改了我的数据库,使得主键变成了序列而不是整数,然后从持久化中删除了id,问题得到了解决。 - monkaORL

1

我之前也遇到了同样的问题,将一个被另一个实体通过OneToMany关系连接的实体的id上的@GeneratedValue注释移除后问题得以解决。


0

我遇到了这个问题。然后在移除了 (cascade = CascadeType.ALL) 后,我的问题得到了解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接