简体   繁体   English

休眠错误:分离的实体传递给持久化

[英]Hibernate error: detached entity passed to persist

I develop a web service with jax-ws, glassfish and hibernate. 我用jax-ws,glassfish和hibernate开发了一个Web服务。 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? 谁能解释这个错误的意思,并提供解决方法的建议?

persist是用于新值,因此请使用merge代替它,因为它看起来certificateRequest请求已经存在

The reason for the error is that the entity instance you are creating already has it's @Id field set. 错误的原因是您正在创建的实体实例已经设置了@Id字段。 Entities with set @Id fields are seen as detached by the persistence provider. 设置了@Id字段的实体被持久性提供程序视为已分离。 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. 通常,应用程序不应定义数据库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. 但是,如果您想使用应用程序生成的ID(例如UUID),则可以为该实体添加一个字段。 Just do not annotate it with @Id . 只是不要使用@Id对其进行注释。 You can and probably should use your application id in your equals and hashCode methods. 您可以并且可能应该在equalshashCode方法中使用应用程序ID。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM