Hibernate未更新数据库记录

问题描述 投票:3回答:1

我正在尝试使用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)

如果您需要,这是我的休眠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>

我提到其他操作,例如插入或读取用户,都可以正常工作。

所以,关于如何执行此更新的任何想法?

java mysql hibernate sql-update deadlock
1个回答
2
投票

这里有很多事情你做错了:

  1. 为什么每次需要调用SessionFactory时都要创建updateYearSessionFactory is an expensive object which should be created during application bootstrap and reused afterward. Use Spring or Java EE for that and inject theSesisonFactory`作为依赖项。

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

  3. 此外,session.close()应在finally块中调用。在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. 正如您从日志中看到的那样,已发出saveOrUpdate,但您却获得了update,因为并发事务已经获得了对此特定记录merge的锁定。如果是这样,您只需要在死锁时重试事务即可。您甚至可以使用UPDATE

© www.soinside.com 2019 - 2024. All rights reserved.