StopKran
StopKran

Reputation: 395

Hibernate error: detached entity passed to persist

I develop a web service with jax-ws, glassfish and hibernate. I have an entity:

@Entity
public class CertificateRequest {

    @Id
    @Column(unique=true, nullable = false)
    @GeneratedValue
    private Long ID;

    @Column(nullable = false)
    private Long terminalID;

    @Column(nullable = false)
    private boolean approved;

    @Column(nullable = false)
    private byte[] rawCertificateRequest;

    @Column(nullable = false)
    private String openTerminalKey;

    @Column(nullable = false)
    private Date requestDate;

    public Long getID() {
        return ID;
    }

    protected CertificateRequest(){
        this.requestDate = new Date();
    }

    public CertificateRequest(long UID, long terminalID, PKCS10 rawCertificateRequest, String openTerminalKey){
        this.ID = UID;
        this.terminalID = terminalID;
        this.rawCertificateRequest = PKCS10toChar(rawCertificateRequest);
        this.openTerminalKey = openTerminalKey;
        this.requestDate = new Date();
        approved = false;
    }

    public CertificateRequest(long UID, long terminalID, byte[] rawCertificateRequest, String openTerminalKey){
        this.ID = UID;
        this.terminalID = terminalID;
        this.rawCertificateRequest = rawCertificateRequest;
        this.openTerminalKey = openTerminalKey;
        this.requestDate = new Date();
        approved = false;
    }

    public Long getTerminalID() {
        return terminalID;
    }

    public void setTerminalID(long terminalID) {
        this.terminalID = terminalID;
    }

    public Boolean isApproved() {
        return approved;
    }

    public void setApproved(boolean approved) {
        this.approved = approved;
    }

    public PKCS10 getRawCertificateRequest(){
        return CharToPKCS10(this.rawCertificateRequest);
    }

    public void setRawCertificateRequest(PKCS10 rawCertificateRequest) {
        this.rawCertificateRequest = PKCS10toChar(rawCertificateRequest);
    }

    public Date getRequestDate() {
        return requestDate;
    }

    public void setRequestDate(Date requestDate) {
        this.requestDate = requestDate;
    }

    public String getOpenTerminalKey() {
        return openTerminalKey;
    }

    public void setOpenTerminalKey(String openTerminalKey) {
        this.openTerminalKey = openTerminalKey;
    }

    private byte[] PKCS10toChar(PKCS10 rawCertificateRequest){
        return  rawCertificateRequest.getEncoded();
    }

    private PKCS10 CharToPKCS10(byte[] rawCharCertificateRequest){
        try {
            return new PKCS10(rawCharCertificateRequest);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

And use it:

public static void createCertificateRequest(long UID, long terminalID, byte[] rawCertificateRequest){
    CertificateRequest certificateRequest = new CertificateRequest(UID, terminalID, rawCertificateRequest, "tmpString");

    EntityManager entityManager = EntityManagerFabric.getEntityManager();
    entityManager.getTransaction().begin();
    entityManager.persist(certificateRequest);
    entityManager.getTransaction().commit();
}

Then I geting error in runtime:

org.hibernate.PersistentObjectException: detached entity passed to persist: org.sigmaps.keyer.models.CertificateRequest
javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: org.sigmaps.keyer.models.CertificateRequest
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1187)
    at org.sigmaps.keyer.handlers.CertificateHandler.createCertificateRequest(CertificateHandler.java:34)
    at org.sigmaps.keyer.CertificateService.requestCertificate(CertificateService.java:20)
    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:606)
    at org.glassfish.webservices.InstanceResolverImpl$1.invoke(InstanceResolverImpl.java:143)
    at com.sun.xml.ws.server.InvokerTube$2.invoke(InvokerTube.java:149)
    at com.sun.xml.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:88)
    at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:1136)
    at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:1050)
    at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:1019)
    at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:877)
    at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:136)
    at org.glassfish.webservices.MonitoringPipe.process(MonitoringPipe.java:142)
    at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:119)
    at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:1136)
    at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:1050)
    at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:1019)
    at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:877)
    at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:136)
    at com.sun.enterprise.security.webservices.CommonServerSecurityPipe.processRequest(CommonServerSecurityPipe.java:210)
    at com.sun.enterprise.security.webservices.CommonServerSecurityPipe.process(CommonServerSecurityPipe.java:142)
    at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:119)
    at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:1136)
    at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:1050)
    at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:1019)
    at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:877)
    at com.sun.xml.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:420)
    at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:687)
    at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:266)
    at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:169)
    at org.glassfish.webservices.JAXWSServlet.doPost(JAXWSServlet.java:169)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
    at java.lang.Thread.run(Thread.java:724)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: org.sigmaps.keyer.models.CertificateRequest
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:139)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181)
    ... 62 more
]]

I can't understand why this error is heppening. Can anybody explain what this error mean, and give advice how to fix that?

Upvotes: 1

Views: 3964

Answers (2)

kostja
kostja

Reputation: 61538

The reason for the error is that the entity instance you are creating already has it's @Id field set. Entities with set @Id fields are seen as detached by the persistence provider. No check against the DB takes place, so it does not matter whether the entity already exists in the DB.

Usually, the application is not supposed to define the DB id. You should rather leave it to the provider.

If you however want use an application-generated id, like a UUID, you can add a field for that to your entity. Just do not annotate it with @Id. You can and probably should use your application id in your equals and hashCode methods.

Upvotes: 3

Karibasappa G C
Karibasappa G C

Reputation: 2732

persist is for new values, so use merge instead of it, because it looks certificateRequest already exists

Upvotes: 2

Related Questions