Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Relation ManyToOne, javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the session

I've spent a lot of time searching for the bug and I can't resolve this. I use spring JPA with Hibernate and Postgre. I have two entities Location and Ap:

    CREATE TABLE ap
(
  id serial NOT NULL,
  ssid text NOT NULL,
  bssid text NOT NULL,
  capabilities text,
  CONSTRAINT ap_pkey PRIMARY KEY (id )
)
CREATE TABLE location2
(
  latitude double precision NOT NULL,
  longitude double precision NOT NULL,
  power integer NOT NULL,
  ap_id integer,
  id serial NOT NULL,
  CONSTRAINT location2_pkey PRIMARY KEY (id ),
  CONSTRAINT location2_ap_id_fkey FOREIGN KEY (ap_id)
      REFERENCES ap (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

Ap:

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "ap")
public class Ap implements Serializable {
    private Long id;
    private String ssid;
    private String bssid;
    private String capabilities;
    private Set<Location> locations = new HashSet<Location>();

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    public Long getId() {
        return id;
    }

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

    @OneToMany(mappedBy = "ap", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    public Set<Location> getLocations() {
        return locations;
    }

    public void setLocations(Set<Location> locations) {
        this.locations = locations;
    }

    @Column
    public String getSsid() {
        return ssid;
    }

    public void setSsid(String ssid) {
        this.ssid = ssid;
    }

    @Column
    public String getBssid() {
        return bssid;
    }

    public void setBssid(String bssid) {
        this.bssid = bssid;
    }

    @Column
    public String getCapabilities() {
        return capabilities;
    }

    public void setCapabilities(String capabilities) {
        this.capabilities = capabilities;
    }

    public void addLocation(Location location) {
        location.setAp(this);
        getLocations().add(location);
    }

    public void removeLocation(Location location) {
        getLocations().remove(location);
    }

    public Ap() {
        super();
    }

    public Ap(String ssid, String bssid, String capabilities) {
        this.ssid = ssid;
        this.bssid = bssid;
        this.capabilities = capabilities;
    }

}

Location2

@Entity
@Table(name = "location2")

public class Location implements Serializable {

    private Long id;
    private double latitude;
    private double longitude;
    private int power;
    private Ap ap;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    public Long getId() {
        return id;
    }

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

    @ManyToOne
    @JoinColumn(name = "ap_id")
    public Ap getAp() {
        return ap;
    }

    public void setAp(Ap ap) {
        this.ap = ap;
    }

    @Column
    public double getLatitude() {
        return latitude;
    }

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

    @Column
    public double getLongitude() {
        return longitude;
    }

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

    @Column
    public int getPower() {
        return power;
    }

    public void setPower(int power) {
        this.power = power;
    }

    public Location(double latitude, double longitude, int power) {
        super();
        this.latitude = latitude;
        this.longitude = longitude;
        this.power = power;
    }

    public Location() {
        super();
    }

When I add one Location to Ap it works, but when Ap has two or more Location I can't save Ap entity.

ApService service=context.getBean("ApService", ApService.class);
    Ap ap=new Ap("test_ssid2", "test_bssid2", "test_capabilities2");
    ap.addLocation(new Location(9.121, 12.9, 12));
    ap.addLocation(new Location(9.122, 12.9, 12));
    service.save(ap);

ApService:

 public Ap save(Ap ap) {
        return apRepository.save(ap);
    }

It cases error:

Exception in thread "main" org.springframework.dao.DataIntegrityViolationException: a different object with the same identifier value was already associated with the session: [com.kulig.ap.domain.Location#9]; nested exception is javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the session: [com.kulig.ap.domain.Location#9]
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:318)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:106)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:403)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy24.save(Unknown Source)
at com.kulig.ap.service.jpa.ApServiceImpl.save(ApServiceImpl.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy29.save(Unknown Source)
at com.kulig.ap.Test.main(Test.java:24)
Caused by: javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the session: [com.kulig.ap.domain.Location#9]
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1359)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1315)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1321)
    at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:843)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
    at $Proxy19.persist(Unknown Source)
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:341)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:334)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:319)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
    ... 22 more

I also tried EntityManager with merge and persist methods and this gives the same error. Please help.

like image 556
Mariusz Avatar asked Sep 14 '12 00:09

Mariusz


1 Answers

In Location try to change

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")

to

@Id
@GeneratedValue(generator="LOCATION_SEQ_GEN",strategy=GenerationType.SEQUENCE)
@SequenceGenerator(sequenceName="location_sequence_name",name="LOCATION_SEQ_GEN",allocationSize=1)

I heard that allocationSize=1 is bad practice but otherwise there are problems with sequence. You can read more Hibernate use of PostgreSQL sequence does not affect sequence table

like image 185
Aleksander Popko Avatar answered Nov 05 '22 05:11

Aleksander Popko