簡體   English   中英

Hibernate驗證失敗時出現意外的UnsupportedOperationException

[英]Unexpected UnsupportedOperationException on Hibernate validation failure

為什么我在驗證失敗時從Hibernate獲得UnsupportedOperationException? 我希望有一個ConstraintViolationException。

下面是我的DAO。 當它通過驗證時,它工作正常。 我正在使用Hibernate和Hibernate Validator 4.我正在使用Websphere 8.0。 我認為WebSphereExtendedJtaPlatform是罪魁禍首,但我不知道為什么。

如果我看一下所謂的WebSphereExtendedJtaPlatform的源代碼(跟隨源代碼的鏈接),看起來大多數方法只會拋出UnsupportedOperationException。

http://grepcode.com/file/repo1.maven.org/maven2/org.hibernate/hibernate-core/4.0.0.CR1/org/hibernate/service/jta/platform/internal/WebSphereExtendedJtaPlatform.java

這是我的堆棧跟蹤:

org.hibernate.AssertionFailure <init> HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: null id in com.westfieldgrp.beanvalidation.persistence.Car entry (don't flush the Session after an exception occurs)
[11/14/12 16:48:48:785 EST] 00000020 RegisteredSyn E   WTRN0074E: Exception caught from before_completion synchronization operation: java.lang.UnsupportedOperationException
    at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter.setRollbackOnly(WebSphereExtendedJtaPlatform.java:139)

我的堆棧跟蹤中另一個有趣的片段:

Entity manager factory name (src_persistence) is already registered.  If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'

這是班級

package com.westfieldgrp.pom.data.dao;

import java.util.ArrayList;
import java.util.Set;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.RollbackException;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import com.westfieldgrp.beanvalidation.persistence.Car;
import com.westfieldgrp.beanvalidation.persistence.Driver;
import com.westfieldgrp.beanvalidation.persistence.Person;

public class CarDAO  {

    private EntityManager entityManager;


    public void save(Person convertedPerson, Driver convertedDriver, Car convertedCar, FacesContext facesContext) throws ConstraintViolationException{
    EntityManager em = getEntityManager();
    //em.setFlushMode(FlushModeType.COMMIT);

    if("test".equals(convertedPerson.getName())){       // To test JPA validation
        convertedPerson.setName(null);
    }
    //Person savedPerson =  em.merge(convertedPerson);
    try {
        //em.merge(convertedPerson);
        em.persist(convertedPerson);
        em.flush();
    } catch (Exception e) {
        System.out.println("*******" + getRootCause(e));
    }
    }

private String getRootCause(Throwable e){
    if(e.getCause() != null){
        return getRootCause(e.getCause());
    } else {
        return e.toString();
    }
}

    public EntityManager getEntityManager() {
            EntityManagerFactory emf = Persistence.createEntityManagerFactory("src_persistence");
            entityManager = emf.createEntityManager();
        return entityManager;
    }

    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
}

人物實體:

package com.westfieldgrp.beanvalidation.persistence;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;

/**
 * The persistent class for the PERSON database table.
 * 
 */
@Entity
@Table(name="PERSON")
public class Person implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="PERSON_ID")
    private int personId;

    @Column(name="NAME")
    @NotNull(message = "A name is required.")
    //@Length(min = 5, message = "Need a longer name.")
    private String name;

    @Column(name="EMAIL")
    @NotNull(message = "An email is required.")
    //@Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email format.")
    private String email;

    public Person() {
    }

    public int getPersonId() {
        return this.personId;
    }

    public void setPersonId(int personId) {
        this.personId = personId;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getEmail() {
        return email;
    }

}

整個堆棧跟蹤:

[11/14/12 19:00:53:202 EST] 0000003c EntityManager Z org.hibernate.ejb.internal.EntityManagerFactoryRegistry addEntityManagerFactory HHH000436: Entity manager factory name (src_persistence) is already registered.  If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'
[11/14/12 19:00:53:214 EST] 0000003c SystemOut     O *******java.lang.UnsupportedOperationException
[11/14/12 19:00:53:214 EST] 0000003c AssertionFail Z org.hibernate.AssertionFailure <init> HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: null id in com.westfieldgrp.beanvalidation.persistence.Person entry (don't flush the Session after an exception occurs)
[11/14/12 19:00:53:215 EST] 0000003c RegisteredSyn E   WTRN0074E: Exception caught from before_completion synchronization operation: java.lang.UnsupportedOperationException
    at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter.setRollbackOnly(WebSphereExtendedJtaPlatform.java:139)
    at org.hibernate.engine.transaction.internal.jta.CMTTransaction.markRollbackOnly(CMTTransaction.java:131)
    at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.setRollbackOnly(TransactionCoordinatorImpl.java:305)
    at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.setRollbackOnly(SynchronizationCallbackCoordinatorImpl.java:118)
    at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:108)
    at org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:53)
    at org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform$TransactionManagerAdapter$TransactionAdapter$1.invoke(WebSphereExtendedJtaPlatform.java:176)
    at $Proxy56.beforeCompletion(Unknown Source)
    at com.ibm.ws.jtaextensions.SynchronizationCallbackWrapper.beforeCompletion(SynchronizationCallbackWrapper.java:66)
    at com.ibm.tx.jta.impl.RegisteredSyncs.coreDistributeBefore(RegisteredSyncs.java:291)
    at com.ibm.ws.tx.jta.RegisteredSyncs.distributeBefore(RegisteredSyncs.java:152)
    at com.ibm.ws.tx.jta.TransactionImpl.prePrepare(TransactionImpl.java:2332)
    at com.ibm.ws.tx.jta.TransactionImpl.stage1CommitProcessing(TransactionImpl.java:553)
    at com.ibm.tx.jta.impl.TransactionImpl.processCommit(TransactionImpl.java:1014)
    at com.ibm.tx.jta.impl.TransactionImpl.commit(TransactionImpl.java:948)
    at com.ibm.ws.tx.jta.TranManagerImpl.commit(TranManagerImpl.java:379)
    at com.ibm.tx.jta.impl.TranManagerSet.commit(TranManagerSet.java:181)
    at com.ibm.ejs.csi.TranStrategy.commit(TranStrategy.java:922)
    at com.ibm.ejs.csi.TranStrategy.postInvoke(TranStrategy.java:234)
    at com.ibm.ejs.csi.TransactionControlImpl.postInvoke(TransactionControlImpl.java:579)
    at com.ibm.ejs.container.EJSContainer.postInvoke(EJSContainer.java:4755)
    at com.westfieldgrp.ejb.EJSLocalNSLCarSessionBean_f700c086.save(EJSLocalNSLCarSessionBean_f700c086.java)
    at com.westfieldgrp.beans.CarBean.processCar(CarBean.java:35)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
    at java.lang.reflect.Method.invoke(Method.java:611)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:262)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
    at org.apache.myfaces.view.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:83)
    at javax.faces.component._MethodExpressionToMethodBinding.invoke(_MethodExpressionToMethodBinding.java:88)
    at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:100)
    at javax.faces.component.UICommand.broadcast(UICommand.java:120)
    at javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:973)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:275)
    at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1285)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:711)
    at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:34)
    at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:171)
    at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:189)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1147)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:722)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:449)
    at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:178)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1020)
    at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:87)
    at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:883)
    at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1659)
    at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:195)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:452)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:511)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:305)
    at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:83)
    at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
    at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
    at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
    at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
    at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
    at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
    at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1648)

我最終根據以下鏈接修改了WebSphereExtendedJtaPlatform代碼。 我很困惑,為什么這個課程基本上沒有實施。

https://forum.hibernate.org/viewtopic.php?f=1&t=992310

我在Websphere Liberty 16.0.0.4上遇到了同樣的問題,並通過更改persistence.xml解決了這個問題:

<property name="hibernate.transaction.jta.platform" value="biz.bitech.hibernate.websphere.WebSphereJtaPlatform" />

以下類需要與hibernate庫一起位於類路徑中:

package biz.bitech.hibernate.websphere;

import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;

import com.ibm.tx.jta.TransactionManagerFactory;
import com.ibm.tx.jta.UserTransactionFactory;
import org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform;

public class WebSphereJtaPlatform extends AbstractJtaPlatform {

    @Override
    protected TransactionManager locateTransactionManager() {
        return TransactionManagerFactory.getTransactionManager();
    }

    @Override
    protected UserTransaction locateUserTransaction() {
        return UserTransactionFactory.getUserTransaction();
    }
}

您可以使用getEntityManager()在每個請求上創建一個新的實體管理器。 您應該請求(例如通過依賴注入)應用程序范圍的持久性管理器。

請注意,您正在接收來自休眠的HHH000099錯誤。 這是由於GeneratedValue返回null並且當hibernate執行插入時,它會將null傳遞給您的PK。

我認為你的ID會隨表自動遞增。 將Generated value設置為AUTO / TABLE / IDENTITY時,Hibernate會在表中查找值。 如果你堅持表,這不應該是一個問題。

我有一個類似的問題,我所做的就是使列成為insertable = false。

希望有所幫助。

下面的代碼來自hibernate-core 4.3.7.FINAL(SynchronizationCallbackCoordinatorNonTrackingImpl)

在重新打包和發送異常之前,您將看到對setRollbackOnly的調用,對於WebSphereExtendedJtaPlatform,它只會拋出一個不受支持的操作異常,這是您在日志中看到的。 此時,由於您從未達到重新打包運行時異常的程度,因此它將丟失。

但不知何故,hibernate設法將其注銷到stdout,因此您將在SystemOut.log文件中找到您的SQL異常

@Override
public void beforeCompletion() {
    LOG.trace( "Transaction before completion callback" );

    if ( !transactionCoordinator.isActive() ) {
        return;
    }

    boolean flush;
    try {
        final int status = transactionCoordinator.getTransactionContext().getTransactionEnvironment()
                .getJtaPlatform().getCurrentStatus();
        flush = managedFlushChecker.shouldDoManagedFlush( transactionCoordinator, status );
    }
    catch ( SystemException se ) {
        setRollbackOnly();
        throw exceptionMapper.mapStatusCheckFailure(
                "could not determine transaction status in beforeCompletion()", se );
    }

    try {
        if ( flush ) {
            LOG.trace( "Automatically flushing session" );
            transactionCoordinator.getTransactionContext().managedFlush();
        }
    }
    catch ( RuntimeException re ) {
        setRollbackOnly();
        throw exceptionMapper.mapManagedFlushFailure( "error during managed flush", re );
    }
    finally {
        transactionCoordinator.sendBeforeTransactionCompletionNotifications( null );
        transactionCoordinator.getTransactionContext().beforeTransactionCompletion( null );
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM