我正在尝试使用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)
如果你需要,这是我的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>
我提到插入或读取用户等其他操作正常工作。
那么,关于如何进行此更新的任何想法?
答案 0 :(得分:2)
这里有很多你做错的事情:
为什么每次需要致电SessionFactory
时都会创建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`作为依赖。
如果抛出异常,则永远不会调用transaction.rollback()
,因此可以保留锁定,直到默认事务超时为止。
此外,应在session.close()
块中调用finally
。在my book, High-Performance Java Persistence, GitHub repository for an example上查看此模板方法。
为什么在使用Hibernate时手动调用UPDATE
?这就是你应该这样做的方式:
User user = session.get(User.class, id);
user.setYear(year);
dirty checking mechanism将为您处理更新there's no need to call saveOrUpdate
, update
or merge
for a managed entity。
正如您从日志中看到的那样,UPDATE
已经发布,但您获得了java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
,因为并发事务已经获得了对此特定记录or for a range of records including this one的锁定。如果是这种情况,您只需要在死锁时重试您的事务。您甚至可以使用auto-retry mechanism。