java Hibernate 验证失败时出现意外的 UnsupportedOperationException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13388069/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unexpected UnsupportedOperationException on Hibernate validation failure
提问by Dale
Why am I getting an UnsupportedOperationException from Hibernate upon validation failure? I'm hoping for a ConstraintViolationException.
为什么我在验证失败时从 Hibernate 收到 UnsupportedOperationException?我希望有一个 ConstraintViolationException。
Below is my DAO. When it passes validation it works fine. I'm using Hibernate and Hibernate Validator 4. I'm using Websphere 8.0. I think WebSphereExtendedJtaPlatform is the culprit, but I have no idea why.
下面是我的 DAO。当它通过验证时,它工作正常。我使用的是 Hibernate 和 Hibernate Validator 4。我使用的是 Websphere 8.0。我认为 WebSphereExtendedJtaPlatform 是罪魁祸首,但我不知道为什么。
If I look at what's supposedly the source code for WebSphereExtendedJtaPlatform (follow link for the source) it looks like most of the methods there just throw UnsupportedOperationException.
如果我看一下 WebSphereExtendedJtaPlatform 的源代码(按照源代码的链接),它看起来像那里的大多数方法只是抛出 UnsupportedOperationException。
Here is my stack trace:
这是我的堆栈跟踪:
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)
Another interesting snippet from my stack trace:
我的堆栈跟踪中的另一个有趣的片段:
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'
Here is the class
这是课堂
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;
}
}
Person entity:
个人实体:
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;
}
}
The whole stack trace:
整个堆栈跟踪:
[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.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.run(ResultHandler.java:905)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1648)
回答by Dale
I ended up modifying the WebSphereExtendedJtaPlatform code according to the following link. I am so baffled why that class was essentially not implemented.
我最终根据以下链接修改了 WebSphereExtendedJtaPlatform 代码。我很困惑为什么那个类基本上没有实现。
回答by busitech
I had the same problem on Websphere Liberty 16.0.0.4, and solved it with a change to persistence.xml:
我在 Websphere Liberty 16.0.0.4 上遇到了同样的问题,并通过对persistence.xml 的更改解决了它:
<property name="hibernate.transaction.jta.platform" value="biz.bitech.hibernate.websphere.WebSphereJtaPlatform" />
The following class needs to be in the classpath along with the hibernate libs:
以下类需要与休眠库一起位于类路径中:
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();
}
}
回答by Hardy
You create a new entity manager on each request using getEntityManager(). You should request (eg via dependency injection) the application wide persistence manager.
您使用getEntityManager()在每个请求上创建一个新的实体管理器。您应该请求(例如通过依赖注入)应用程序范围的持久性管理器。
回答by Aadil
Please note that you are recieving the HHH000099 error from hibernate. This is due to the GeneratedValue returning null and when hibernate does an insert, it passes a null to your PK.
请注意,您从休眠中收到 HHH000099 错误。这是由于 GeneratedValue 返回 null 并且当 hibernate 执行插入操作时,它会将 null 传递给您的 PK。
I take it that your ID is auto incremented withing the table. When you set Generated value to AUTO/TABLE/IDENTITY, Hibernate looks for the value in the table. It shouldnt be a problem if you persist the table.
我认为您的 ID 是随表自动递增的。当您将 Generated value 设置为 AUTO/TABLE/IDENTITY 时,Hibernate 会在表中查找该值。如果您坚持该表,这应该不是问题。
I had a similar issue and all i did was make the column as insertable=false.
我有一个类似的问题,我所做的只是将列设置为可插入 = 假。
Hope that helps.
希望有帮助。
回答by Legna
the code below is from hibernate-core 4.3.7.FINAL (SynchronizationCallbackCoordinatorNonTrackingImpl)
下面的代码来自 hibernate-core 4.3.7.FINAL (SynchronizationCallbackCoordinatorNonTrackingImpl)
you will see a call to setRollbackOnly just before the exception is re-package and sent, for WebSphereExtendedJtaPlatform it simply throws an unsupported operation exception, which is what you see on the logs. At this point, as you never reach the point where your runtime exception is re-packaged, it is lost.
您将在重新打包和发送异常之前看到对 setRollbackOnly 的调用,对于 WebSphereExtendedJtaPlatform,它只是抛出一个不受支持的操作异常,这就是您在日志中看到的内容。此时,由于您永远不会到达重新打包运行时异常的点,因此它丢失了。
But somehow hibernate manages to log it out to the stdout, so you will find your SQL exception in your SystemOut.log file
但不知何故,休眠设法将其注销到标准输出,因此您会在 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 );
}
}