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

时间:2012-06-01 18:29:15

标签: mysql windows hibernate jsf-2 jboss

我有一个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(下面的配置)

  5. 知道发生了什么事吗?

    代码详情:

    这发生在地址对象上。这是完整的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>
    

    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;
    }
    
    }
    

    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>
    

    使用的版本是

    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
    

    完整的堆栈跟踪

    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)
    

19 个答案:

答案 0 :(得分:39)

例外:

  

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

告诉我们会话异常发生在之前抛出此org.hibernate.AssertionFailure的位置。

确切地说,当org.hibernate.AssertionFailure发生时,session.flush()被抛出,而不是发生错误的点。

以上是一个事实,因此可能的结论是:某些东西可能压制原始异常。

因此,请查找其他可能的错误点:save()saveOrUpdate()可能尝试保留具有null字段<的实体/ strong>在表中,列是NOT NULL


提示 为了帮助调试,请尝试在与session.flush()对象(例如Sessionsession.save(obj)等)的每次互动后添加session.merge(obj),这有望导致{org.hibernate.AssertionFailure 1}}更早发生,更接近发生真正问题的地方。 (当然,在调试之后,删除那些session.flush()。)


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

答案 1 :(得分:11)

我打赌会出现并发问题,但可能会出现在不同的级别:

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

答案 2 :(得分:6)

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

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

{{1}}

这有助于因为所有的“肮脏”。从当前会话中删除对象,因此当执行下一次刷新时,问题不会出现。

示例流程:

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

示例正确的流程:

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

希望它有所帮助;)

答案 3 :(得分:3)

你可能遇到了一些Hibernate错误。 (我建议至少升级到Hibernate 3.3.2.GA.)

同时,当你的ID可以为空时,Hibernate会做得更好,这样Hibernate总能分辨出一个尚未持久保存到数据库的新对象和已经存在于数据库中的对象。将addressID的类型从long更改为Long可能会解决此问题。

您提供的堆栈跟踪显示您在查询中看到问题,因为您的查询强制缓冲写入在执行查询之前被刷新到数据库并且写入失败,可能与其他人的插入问题相同正在看到。

答案 4 :(得分:2)

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

亲切的问候: Shahid Hussain Abbasi

答案 5 :(得分:1)

在我的情况下,问题出在实体字段的长度参数上。当我尝试在其字段之一中保存字符串值过长的对象时,出现错误。解决方案是在休眠配置中设置参数“ length”的适当值。

@Length(max=150)
private String status;

也可以使用@Length注释来完成:

Hire Date             Term Date = "end date"          
01/01/2019            05/01/2020
05/04/2018            
09/17/2019            03/18/2020
10/19/2018

在我的案例中,休眠异常的消息非常令人误解,stacktrace也是如此。定位问题发生位置的最快方法是使用调试器跟踪代码,并在每个 save() saveOrUpdate()之后评估 session.flush(); 方法。

答案 6 :(得分:1)

这是在以下情况下发生的:

  1. 新实体被保留。

  2. 实体使用asp.net core 3.x配置。 public async Task<HttpResponseMessage> UploadFile(string param1, string param2, string fileName, [FromBody] byte[] arrayBuffer) { try { var response = await xyz.UploadFile(param1, param2, fileName, arrayBuffer); var httpResponse = Request.CreateResponse(HttpStatusCode.Created); httpResponse.Content = new StringContent(response, Encoding.UTF8, "application/json"); return httpResponse; } catch (Exception e) { return Request.CreateResponse(HttpStatusCode.InternalServerError, e.ToString()); } } 运行。

  3. javax.persistence.EntityListeners需要数据库中的一些数据才能通过javax.persistence.PostPersist发送消息。执行PostPersist查询。

  4. 异常。

我通过在STOMP中使用以下内容对其进行了修复:

org.springframework.data.repository.PagingAndSortingRepository

EntityListeners定义为:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.time.Instant;
...

ThreadPoolTaskScheduler scheduler = ApplicationContextHolder.getContext().getBean(ThreadPoolTaskScheduler.class);
scheduler.schedule(() -> repository.query(), Instant.now());

答案 7 :(得分:1)

问题流:

  1. 您创建一个新的临时实体实例(这里是一个地址实例)
  2. 您将其持久化到数据库中(使用保存,合并或持久化在休眠会话/ JPA EntityManager中)
  3. 由于实体标识符是由数据库生成的,因此hibernate必须触发数据库插入(刷新会话)以检索生成的id
  4. 插入操作触发异常(或会话中任何未处理的未更改更改)
  5. 您捕获了异常(不传播该异常)并恢复执行流程(此时,您的会话仍包含不带id的未持久实例,问题在于休眠似乎将实例视为托管实例,但实例已损坏,原因是:被管理对象必须具有ID)
  6. 您到达工作单元的末端,并且在提交当前事务之前会自动刷新会话,由于会话包含已损坏的实例,刷新会失败,并会导致断言失败

您可以通过多种方法来减轻此错误:

  • 最简单的休眠状态,即“发生异常后不要刷新Session”。持久性异常发生后立即放弃并回滚当前事务。
  • 在捕获到错误后手动从会话中逐出(JPA:分离)损坏的实例(在第5点,但是如果该错误是由另一个挂起的更改而不是实体插入本身触发的,则将是无效的)
  • 不要让数据库处理id的生成(使用UUID或分布式id生成系统,在这种情况下,最后的刷新将抛出真实的错误,从而防止新实例的持久性,而不是休眠断言失败)

答案 8 :(得分:0)

就我而言,我追踪了错误并发现我没有将表的主键(即“ID”)标记为“Auto_Increment”AI。只需勾选 AI 复选框,它就会起作用。 enter image description here

答案 9 :(得分:0)

我在创建session.getCurrentSession.refresh(entity)时遇到了相同的错误,它对我来说似乎更像是一个错误,而不是我的代码有问题。当我尝试在测试开始时刷新实体并且该实体在测试设置中创建时(在junit的@Before注释中),我在单元测试中遇到此错误。奇怪的是,我要在同一时间使用相同的方法在同一类中创建3个实体,并且在设置中以相同的方式进行创建,并且可以刷新创建的前两个实体,但是最后一个刷新失败。因此,例如,如果我在测试设置中创建了3个实体User,则可以刷新user1和user2,而user3则失败。我可以通过在安装程序中创建实体的代码末尾添加session.flush()来解决此问题。我没有任何错误,但我应该这样做,但是我无法解释为什么需要额外的冲洗。另外,即使我没有刷新,我也可以确认实体确实在测试数据库中,因为我可以在测试中查询它们,但是仍然无法执行refresh(entity)方法。

答案 10 :(得分:0)

我有同样的错误。就我而言,这是因为在此异常之前,我执行带异常的创建查询。捕获异常,不要在catch块中回滚事务。然后,我在其他操作中使用了这个中断的事务,过了一段时间,我得到了同样的异常。首先,我将冲洗模式设置为手动

public final Session getCurrentSession()  
{
    Session session = sessionFactory.getCurrentSession();
    session.setFlushMode(FlushMode.MANUAL);
    return session;
}

然后我又遇到了一个例外,这向我解释了实际上发生了什么。然后,在我的create方法的catch块中完成了事务回滚。这对我有所帮助。

答案 11 :(得分:0)

org.hibernate.AssertionFailure:条目中的ID为null(发生异常后不要刷新Session)

如果您维护用户活动的版本历史记录并尝试设置以下值,则在使用save方法时遇到此错误         setCreatedBy(1); setModifiedBy(1); setCreationDate(); setChangeDate(); } 您将收到上述错误来解决此问题,您需要在表上创建以下列。

Created_By Modified_By Creation_Date Change_Date 如果在使用Update方法解决此问题时遇到相同的错误,只需将它的Update()方法更改为merge()方法即可 希望对您有所帮助。

答案 12 :(得分:0)

有时,当字符串的长度大于DB允许的长度时,就会发生这种情况。

ax.spines['bottom'].set_color('white') ax.spines['top'].set_color('white') ax.spines['right'].set_color('white') ax.spines['left'].set_color('white') 转换为此异常,这是休眠状态下的怪异行为。

因此,如果您在具有指定长度的实体的String字段上具有DataIntegrityViolationException注释,并且实际值大于该长度,则会引发上述异常。

参考:https://developer.jboss.org/thread/186341?_sscc=t

答案 13 :(得分:0)

我在hibernate配置文件中也有同样的例外:

<property name="operateType" type="java.lang.Integer">
        <column name="operate_type" not-null="true" />
 </property>

当在对象上传递null值时,发生异常

 "org.hibernate.AssertionFailure: null id in com.idex.auctions.model.Address entry",

我认为原因是因为Hibernaye会检查&#39; not-null&#39;属性,所以,删除&#39; not-null&#39;属性或设置&#39; not-null&#39;对于&#39; false&#39;,将解决问题。

答案 14 :(得分:0)

  

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

这恰好发生在我们身上,我想我会为后代添加一些细节。事实证明我们正在尝试创建一个具有违反条件的重复字段的实体:

Caused by: org.hibernate.exception.ConstraintViolationException: Duplicate entry '' for key
'Index_schools_name'

然而,这个异常被掩盖了,因为即使创建失败,hibernate也试图提交会话。当创建失败时,则未设置id,因此断言错误。在堆栈跟踪中,我们可以看到hibernate正在提交:

at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit
(HibernateTransactionManager.java:480)

应该回滚会话,而不是提交会议。这对我们的回滚配置来说是一个问题。我们使用旧的XML配置,异常路径不正确:

<prop key="create*">PROPAGATION_REQUIRED,-org.x.y.LocalException</prop>

LocalException路径不正确,并且hibernate没有抛出错误(或者它被隐藏在启动日志中)。如果您使用注释并且没有指定正确的例外情况,情况可能就是这样:

// NOTE: that the rollbackFor exception should match the throws (or be a subclass)
@Transactional(rollbackFor = LocalException.class)
public void create(Entity entity) throws AnotherException {

一旦我们修复了我们的休眠线路,我们就会正确地看到&#34;重复的条目&#34;异常,会话正在回滚和关闭。

另外一个问题是,当hibernate抛出AssertionFailure时,它在MySQL中持有一个事务锁,然后必须手动杀死它。请参阅:https://stackoverflow.com/a/39397836/179850

答案 15 :(得分:0)

更改生成器类:

<generator class="identity" />

<generator class="assigned" />

答案 16 :(得分:0)

好的,我继续研究这个主题中的其他答案。但最终,由于我们在生产截止日期之前,我不得不选择紧急溃败。因此,我没有弄清楚hibernate,而是做了这两件事:

  1. 删除了我用来抓住其中一个表单的jQuery库。我之所以这样做是因为我在某处读到了这种类型的错误可能是由于表单发布了一个空值 - 导致null id下线。我怀疑jQuery库可能不适合PrimeFaces,并导致某些形式出现故障。只是一种预感。

  2. 我杀死了用户和地址之间的hibernate实现关系。 (只需要一个,而不是一个到多个)并在需要时自己编写代码。幸运的是,它只影响了一个页面,所以它没有多少工作。

  3. 底线:我们上线了,应用程序已经运行了好几天没有任何错误。所以这个解决方案可能并不漂亮 - 而且我并不为自己感到自豪 - 但我有一个正在运行的应用程序和一个快乐的客户端。

答案 17 :(得分:0)

这与正在执行的查询无关。这只会触发冲洗。此时,Hibernate正在尝试为实体分配一个标识符,并且由于某种原因似乎已经失败了。

您可以尝试更改生成器类:

<generator class="identity"/>

看看是否有所作为。您还确保已部署的数据库在表上设置了正确的自动递增列吗?

听起来您的问题类似于this one

答案 18 :(得分:-1)

在catch块中回滚您的事务