org.hibernate.AssertionFailure:条目中的null id(发生异常后不刷新会话)

Her*_*zog 47 mysql windows jboss hibernate jsf-2

我有一个hibernate和JSF2应用程序进入部署服务器并突然在异常中抛出org.hibernate.AssertionFailure:null id.我将立即提供堆栈跟踪和代码,但这里首先是四个重要问题:

  1. 这只发生在部署服务器上(在Windows Sever 2008上运行的Jboss和MySql).它不会发生在我的开发机器上(在Windoes 7 Pro上运行的Tomcat和MySql),也不会发生在暂存环境中(在Linux上运行的Jboss和MySql) .)

  2. 研究这个,似乎人们在尝试插入对象时会出现此错误.但是当我做一个简单的查询时,我得到了错误.(实际上,各种不同的查询随机地在几个页面上弹出错误.)

  3. 错误只会偶尔出现.如果我做Jboss重启它会消失,但一段时间后会返回.此外,它不一致,有些点击它在那里,而其他人则没有.即使它命中,当我对页面进行简单的刷新时它也会返回.

  4. 我正在使用c3p0(下面的配置)

知道发生了什么事吗?

代码详情:

这发生在地址对象上.这是完整的hbm:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.idex.auctions.model">
<class name="Address" table="address" lazy="true">
  <id name="addressID" column="AddressID">
        <generator class="native"/>            
  </id>

  <property name="street" column="street"/> 
  <property name="city" column="city"/> 
  <property name="zip" column="zip"/> 
  <property name="state" column="state"/> 
  <property name="region" column="region"/> 
  <property name="country" column="country"/> 

  <many-to-one name="user" 
       class="com.idex.auctions.model.User" 
       column="userid" 
       unique="true" 
       cascade="save-update"/>
 </class> 
</hibernate-mapping>
Run Code Online (Sandbox Code Playgroud)

Java类是直截了当的:

public class Address implements Serializable {
private static final long serialVersionUID = 7485582614444496906L;

private long addressID;
private String street;
private String city;
private String zip;
private String state;
private String region;
private String country;
private User user;

public Address() {

}
public long getAddressID() {
    return addressID;
}
public void setAddressID(long addressID) {
    this.addressID = addressID;
}
public String getStreet() {
    return street;
}
public void setStreet(String street) {
    this.street = street;
}
public String getCity() {
    return city;
}
public void setCity(String city) {
    this.city = city;
}
public String getZip() {
    return zip;
}
public void setZip(String zip) {
    this.zip = zip;
}
public String getState() {
    return state;
}
public void setState(String state) {
    this.state = state;
}
public String getRegion() {
    return region;
}
public void setRegion(String region) {
    this.region = region;
}
public String getCountry() {
    return country;
}
public void setCountry(String country) {
    this.country = country;
}
public User getUser() {
    return user;
}
public void setUser(User user) {
    this.user = user;
}

}
Run Code Online (Sandbox Code Playgroud)

c3p0配置:

<property name="hibernate.c3p0.acquire_increment">1</property> 
<property name="hibernate.c3p0.idle_test_period">1000</property> 
<property name="hibernate.c3p0.max_size">20</property>  
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.max_statements">0</property>
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
Run Code Online (Sandbox Code Playgroud)

使用的版本是

hibernate3.jar

c3p0-0.9.1.2.jar

myfaces-api-2.1.4.jar

myfaces-impl-2.1.4.jar

mysql-connector-java-5.1.20-bin.jar
Run Code Online (Sandbox Code Playgroud)

完整的堆栈跟踪

org.hibernate.AssertionFailure: null id in com.idex.auctions.model.Address entry 
    (don't flush the Session after an exception occurs)
org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(
                                          DefaultFlushEntityEventListener.java:78)
org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(
                                          DefaultFlushEntityEventListener.java:187)
org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(
                                          DefaultFlushEntityEventListener.java:143)
org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(
                                          AbstractFlushingEventListener.java:219)
org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(
                                          AbstractFlushingEventListener.java:99)
org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(
                                          DefaultAutoFlushEventListener.java:58)
org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:997)
org.hibernate.impl.SessionImpl.list(SessionImpl.java:1142)
org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
com.idex.auctions.manager.DatabaseManager.getAllObjects(DatabaseManager.java:464)
com.idex.auctions.ui.NavBean.gotoHome(NavBean.java:40)
sun.reflect.GeneratedMethodAccessor350.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
javax.el.BeanELResolver.invokeMethod(BeanELResolver.java:735)
javax.el.BeanELResolver.invoke(BeanELResolver.java:467)
javax.el.CompositeELResolver.invoke(CompositeELResolver.java:246)
org.apache.el.parser.AstValue.getValue(AstValue.java:159)
org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)
org.apache.myfaces.view.facelets.el.ContextAwareTagValueExpression.getValue(
                                          ContextAwareTagValueExpression.java:96)
javax.faces.component._DeltaStateHelper.eval(_DeltaStateHelper.java:246)
javax.faces.component.UIOutcomeTarget.getOutcome(UIOutcomeTarget.java:50)
org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils.getOutcomeTargetHref(
                                          HtmlRendererUtils.java:1542)
org.apache.myfaces.shared.renderkit.html.HtmlLinkRendererBase.renderOutcomeLinkStart(
                                          HtmlLinkRendererBase.java:908)
org.apache.myfaces.shared.renderkit.html.HtmlLinkRendererBase.encodeBegin(
                                          HtmlLinkRendererBase.java:143)
javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:502)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:744)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:758)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:758)
org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(
                                    FaceletViewDeclarationLanguage.java:1900)
org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:285)
com.ocpsoft.pretty.faces.application.PrettyViewHandler.renderView(
                                    PrettyViewHandler.java:163)
javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:59)
org.apache.myfaces.tomahawk.application.ResourceViewHandlerWrapper.renderView(
                                    ResourceViewHandlerWrapper.java:93)
com.idex.auctions.ui.CustomViewHandler.renderView(CustomViewHandler.java:98)
org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:115)
org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:126)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:118)
Run Code Online (Sandbox Code Playgroud)

acd*_*ior 43

例外:

org.hibernate.AssertionFailure:条目中的null id(发生异常后不刷新会话)

告诉我们,本次会议异常发生,其中这点org.hibernate.AssertionFailure抛出.

确切地说,org.hibernate.AssertionFailuresession.flush()发生时抛出,而不是发生错误的点.

以上是一个事实,因此可能的结论是:有些东西可能会抑制原始异常.

因此,寻找其他可能的错误点:A save()或者saveOrUpdate()可能尝试持有一个null字段的实体,表中的列是NOT NULL


提示: 为了帮助调试,尝试添加一个session.flush()与每一次交互后Session的对象(例如session.save(obj),session.merge(obj)等),希望这将导致org.hibernate.AssertionFailure更早发生,更加接近其真正的问题正在发生.(当然,在调试之后,删除那些session.flush().)


在我的情况下,真正的异常发生在一个try/catch {}阻止异常的块内catch(没有重新抛出或警告我).

  • 你如何解决这个问题?我试图在循环中保存许多实体。其中一些可能会失败。我怎样才能让成功的记录持久化? (2认同)
  • 也许这是一个很好的机会来注意空 catch 块是多么危险,它们可能需要数周的时间来排除故障!总是有一些东西可以引起开发人员的注意,至少是 .printStackTrace。如果您绝对确定希望它为空(受检异常可能会导致这种情况),请在注释中证明这一点。 (2认同)

Yve*_*tin 12

我敢打赌并发问题,但它可能发生在不同的层面:

除了这些潜在的麻烦来源之外,我会删除c3p0(可能只是谣言......),因为您的堆栈已经提供DataSource了与事务管理器集成的连接池.


Prz*_*wak 6

@asdcjunior已正确回答.在抛出异常之前发生了一些事情.

在这种情况下(当你为一个测试处理单个事务时,它经常发生在集成测试中 - 例如@Transaction注释)我正在调用该方法:

session.clear()
Run Code Online (Sandbox Code Playgroud)

它有帮助,因为所有'脏'对象都从当前会话中删除,因此当执行下一次刷新时,问题不会出现.

示例流程:

  • 插入赋值实体(多对多关系,可以只存在单个赋值的约束) - >一切正常
  • 再次插入相同的赋值实体 - >一切正常,控制器在这种情况下返回某种不良请求异常,引擎盖下Spring抛出IntegrityViolationException - >在测试中一切看起来都好
  • 获取存储库并执行findAll().size()以检查已存在的已分配计数,以确保我们只有单个赋值 - >抛出提到的异常; /发生了什么?在会话上仍然存在脏对象,通常会话会被销毁(控制器返回错误)但是这里我们有下一个关于数据库检查的断言,所以这里的解决方案是在下一个db相关方法执行之前的附加session.clear()

正确流程示例:

  • 插入赋值实体
  • 插入相同的赋值实体
  • session.clear()
  • 获取存储库并执行findAll().size()

希望能帮助到你 ;)

  • 这是减轻 pb 的最危险的方法,如果您在会话中还有其他未刷新的挂起更改,而您的实体未能插入,则所有内容都将丢失,这可能会导致您的工作单元中出现完全意外的行为 (2认同)

Sha*_*asi 5

我遇到了这个问题,我只是添加了 try catch 块,并在 catch 块中写了 seesion.clear(); 现在我可以继续将其余记录插入数据库中。

  • 这是减轻 pb 的最危险的方法,如果您在会话中还有其他未刷新的挂起更改,而您的实体未能插入,则所有内容都将丢失,这可能会导致您的工作单元中出现完全意外的行为 (2认同)