3

I'm trying to update an existing object from the database using Hibernate.

I run the code, and it doesn't give me any errors, but it's also not updating the database. I searched for the problem but I can't see where is my mistake.

Here is my function from userDAO class:

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

        }

And here is just how I call it:

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

The result is something like this:

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=?

Also sometimes, I recieve this error, but not exactly after running, I find it weird:

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)

In case u need, this is my hibernate 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>

I mention that other operations like inserting or reading users it's working properly.

So, any ideas on how can I do this update?

1
  • 1
    Do you have a User POJO? If so, I think Hibernate can't find a User instance that matches your condition (id=1) and consequently doesn't update anything. Usually you can use Session.get(User.class, id) to retrieve the User instance and update that instance directly (Session.update(user) ) Commented Aug 27, 2017 at 14:43

1 Answer 1

2

There are so many things you are doing wrong here:

  1. Why are you creating the SessionFactory every time you need to call updateYear? SessionFactory is an expensive object which should be created during application bootstrap and reused afterward. Use Spring or Java EE for that and inject the SesisonFactory` as a dependency.

  2. If an Exception is thrown, you never call transaction.rollback() so locks can be kept until for the duration of the default transaction timeout.

  3. Also, session.close() should be called in a finally block. Check out this Template method on the High-Performance Java Persistence GitHub repository.

  4. Why do you call UPDATE manually when you use Hibernate? This is how you should do it:

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

    The dirty checking mechanism will take care of the UPDATE for you so there's no need to call saveOrUpdate, update, or merge for a managed entity.

  5. As you can see from the logs, the UPDATE was issued but you got the java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction because a concurrent transaction has already acquired the lock on this particular record or for a range of records including this one. If that's the case, you just need to retry your transaction upon deadlock. You can even use an auto-retry mechanism.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot for all those explanations. I got the code to work without those anyway, but it's far from being a good implementation. I will really read everything you suggested me and do the changes acordingly. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.