2012-09-14 8 views
6

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.

risposta

1

In posizione tenta di modificare

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

a

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

ho sentito che allocationSize=1 è cattiva pratica, ma altrimenti ci sono problemi con la sequenza. Puoi leggere di più Hibernate use of PostgreSQL sequence does not affect sequence table

+1

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. –

Problemi correlati