Ho passato molto tempo a cercare il bug e non riesco a risolverlo. Io uso JPA a molla con Hibernate e Postgre. Ho due entità di localizzazione e AP:Relazione ManyToOne, javax.persistence.EntityExistsException: un oggetto diverso con lo stesso valore identificativo era già associato alla sessione
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();
}
Quando aggiungo un luogo ad Ap funziona, ma quando Ap ha due o più Posizione Non posso salvare l'entità Ap.
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 casi di errore:
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
Ho provato anche con EntityManager merge e persistono i metodi e questo dà lo stesso errore. Per favore aiuto.
Il parametro allocationSize descrive quanti numeri di sequenza tirare per il recupero del DB. Questo riguarda le prestazioni. Se impostato su "10", il contenitore incrementerà la sequenza di 10 nel DB e manterrà l'N-10 in memoria. Quando è necessario un valore, esaurirà il pool in memoria prima di eseguire nuovamente il recupero dal DB. Questo potenzialmente "brucia" i numeri di sequenza inutilizzati a vantaggio di prestazioni migliori. Sospetto che il gestore di sequenze di Hibernate (che non ha nulla a che fare con l'implementazione del DB) non stia mantenendo la traccia corretta del pool di sequenze in memoria. –