休眠不更新数据库记录

问题描述:

我试图从数据库使用Hibernate更新现有的对象。休眠不更新数据库记录

我运行的代码,它不给我任何错误,但它也没有更新数据库。我搜索了这个问题,但我看不出我的错误在哪里。

这里是userDAO类我的功能:

public void updateYear(int id, int year) { 
      try { 

       Configuration configuration = new Configuration().configure(); 
       SessionFactory sessionFactory = configuration.buildSessionFactory(); 
       Session session = sessionFactory.openSession(); 
       Transaction transaction = null; 
       transaction = session.beginTransaction(); 


      String hql = "UPDATE User u set u.year= :year WHERE u.id= :id"; 
      Query query=session.createQuery(hql).setParameter("year", year).setParameter("id", id); 
      int result = query.executeUpdate(); 
      System.out.println("Rows affected: " + result+"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 


      transaction.commit(); 
      session.close(); 

      } catch (HibernateException e) { 
       System.out.println(e.getMessage()); 
       System.out.println("error"); 
      } 

     } 

,这里是我刚才怎么称呼它:

UserDAO u = new UserDAO(); 
     u.updateYear(1,6); 

的结果是这样的:

aa DEBUG org.hibernate.hql.internal.ast.ErrorCounter: throwQueryException() : no errors 
aa DEBUG org.hibernate.hql.internal.ast.ErrorCounter: throwQueryException() : no errors 
aa DEBUG org.hibernate.SQL: 
    update 
     user 
    set 
     year=? 
    where 
     id=? 
Hibernate: 
    update 
     user 
    set 
     year=? 
    where 
     id=? 

而且有时,我收到这个错误,但不是完全运行后,我觉得很奇怪:

aa DEBUG org.hibernate.engine.jdbc.spi.SqlExceptionHelper: could not execute statement [n/a] 
java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028) 
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490) 
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651) 
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2683) 
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2144) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2444) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2362) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2347) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:205) 
    at org.hibernate.hql.internal.ast.exec.BasicExecutor.doExecute(BasicExecutor.java:90) 
    at org.hibernate.hql.internal.ast.exec.BasicExecutor.execute(BasicExecutor.java:59) 
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.executeUpdate(QueryTranslatorImpl.java:437) 
    at org.hibernate.engine.query.spi.HQLQueryPlan.performExecuteUpdate(HQLQueryPlan.java:374) 
    at org.hibernate.internal.SessionImpl.executeUpdate(SessionImpl.java:1510) 
    at org.hibernate.query.internal.AbstractProducedQuery.doExecuteUpdate(AbstractProducedQuery.java:1526) 
    at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1504) 
    at dao.UserDAO.updateYear(UserDAO.java:160) 
    at Main.main(Main.java:52) 

如果u需要,这是我的休眠CFG:

<hibernate-configuration> 
    <session-factory> 
     <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 
     <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/licenta</property> 
     <property name="hibernate.connection.username">root</property> 
     <property name="hibernate.connection.password">root</property> 
     <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 
     <property name="show_sql">true</property> 
     <property name="format_sql">true</property> 
     <property name="hbm2ddl.auto">validate</property> 
     <property name="hibernate.show_sql">true</property> 

     <mapping resource="user.hbm.xml"/> 
     <mapping resource="chapter.hbm.xml"/> 
     <mapping resource="comments.hbm.xml"/> 
     <mapping resource="problems.hbm.xml"/> 
     <mapping resource="questions.hbm.xml"/> 

    </session-factory> 
</hibernate-configuration> 

我提到的其他操作,如插入或读取它的正常工作的用户。

因此,有关如何进行此更新的任何想法?

+1

您是否有用户POJO?如果是这样,我认为Hibernate找不到符合条件的用户实例(id = 1),因此不会更新任何内容。通常,您可以使用Session.get(User.class,id)来检索User实例并直接更新该实例(Session。更新(用户)) –

有你做错了事情太多了:

  1. 你为什么要创建每次你需要调用updateYear时间SessionFactory? `SessionFactory是一个昂贵的对象,应该在应用程序引导过程中创建并在之后重用。使用Spring或Java EE,并将Sesisonfactory注入为依赖项。

  2. 如果抛出异常,您永远不会调用transaction.rollback(),因此锁可以保留到默认事务超时期间。

  3. 另外,应该在finally块中调用session.close()块。请在my book, High-Performance Java Persistence, GitHub repository for an example上查看此模板方法。

  4. 为什么在使用Hibernate时手动调用UPDATE?这是你应该怎么做:

    User user = session.get(User.class, id); 
    user.setYear(year); 
    

    dirty checking mechanism会照顾UPDATE对你这么there's no need to call saveOrUpdate, update or merge for a managed entity

  5. 你可以从日志中看到,UPDATE发出,但你得到了java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction因为并发事务已经收购了在这个特别的记录or for a range of records including this one锁。如果是这样的话,你只需要在死锁时重试你的事务。你甚至可以使用auto-retry mechanism

+0

非常感谢所有这些解释。无论如何,我得到的代码无需工作,但它远不是一个好的实现。我会真正阅读你建议我的一切,并根据情况进行修改。谢谢! –

+0

如有疑问,请前往[vladmihalcea.com](https://vladmihalcea.com)。 –