我是Hibernate的新手。我有一个问题,当我尝试运行选择查询说
"from Foo where Foo.some_id=2"
(使用Hibernate模板)然后Hibernate也尝试将记录插入到表'Foo2'中,该表与Foo表具有一对二的关联
Bean Foo
class Foo{
int id;
....
Foo2 foo2;
}
Foo.hbm.xml
...
<one-to-one name="foo2" class="Foo2" property-ref="foo"
constrained="false" cascade="save-update"></one-to-one>
...
Bean Foo2
Class Foo2{
...
private int foo;
...
}
Foo2.hbm.xml
...
<property name="foo" column="foo_id"/>
...
用法
DetachedCriteria criteria = createDetachedCriteria();
criteria.add(Restrictions.eq("some_id", value));
return getHibernateTemplate().findByCriteria(criteria);
public List<SnsUser> getAllSnsUsersByProperty(String prop, Object val){
String query = "from SnsUser su where su." + prop + " =:" + prop;
return executeQuery(query, new String[]{prop}, new Object[]{val});
}
public static void main(String[] args) { //WORKING
String query = "from SnsUser su where su.blessUserId=1";
Session session = Utility.getSessionFactory().openSession();
List l = new SnsUserDaoImpl().getQRes(query);
System.out.println(l);
session.close();
}
public List<E> executeQuery(String queryString, String []param, Object [] val){
//NOT WORKING
return getHibernateTemplate().findByNamedParam(queryString, param, val);
}
这就是我得到的......
Hibernate: select * from bless_aggregation.sns_user this_ left outer join bless_aggregation.sns_authenticator snsauthent2_ on this_.sns_uid=snsauthent2_.sns_uid
where this_.bless_uid=?
Hibernate: select * from bless_aggregation.bless_user blessuser0_ where blessuser0_.bless_uid=?
Hibernate: select * from bless_aggregation.sns_user snsuser0_ left outer join bless_aggregation.sns_authenticator snsauthent1_ on
snsuser0_.sns_uid=snsauthent1_.sns_uid where snsuser0_.bless_uid=?
Hibernate: insert into bless_aggregation.sns_authenticator (key, value, sns_uid) values (?, ?, ?)
1079 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1064, SQLState: 42000
1079 [main] ERROR org.hibernate.util.JDBCExceptionReporter - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key, value, sns_uid) values (null, null, 1)' at line 1
答案 0 :(得分:5)
我的猜测是你在会话中有待更改(某些Foo2实例等待插入),默认情况下,Hibernate会在运行查询之前刷新会话,以便为您提供非陈旧的结果。这在文档的以下部分中进行了解释:
10.10. Flushing the Session
有时会话会执行 需要同步的SQL语句 JDBC连接的状态与 内存中保存的对象状态。这个 进程,称为刷新,发生 默认为以下几点:
在某些查询执行之前
- 来自org.hibernate.Transaction.commit()
- 来自Session.flush()
SQL语句发布于 以下顺序:
- 所有实体插入的顺序与相应的对象相同 使用
保存Session.save()
- 所有实体更新
- 所有集合删除
- 所有集合元素删除,更新和插入
- 所有收集插入
- 所有实体删除的顺序与对应的对象相同 已使用
删除 醇>Session.delete()
一个例外是对象使用 插入本机ID时生成 他们得救了。
除非您明确
flush()
, 绝对没有保证 关于Session何时执行 JDBC调用,只有其中的顺序 他们被处决了。 然而,Hibernate 确保保证Query.list(..)
永远不会回来 陈旧或不正确的数据。可以更改默认值 行为使得冲洗发生得更少 频繁即可。
FlushMode
课程 定义了三种不同的模式:仅 在提交时刷新 使用Hibernate Transaction API , 使用自动冲洗 解释常规,或从不冲洗 除非明确调用flush()。 最后一种模式很有用 运行工作单元,其中一个会话 保持打开状态并断开连接 很长时间(见第11.3.2节, “扩展会话和自动 版本”)。sess = sf.openSession(); Transaction tx = sess.beginTransaction(); sess.setFlushMode(FlushMode.COMMIT);
//允许查询返回陈旧状态
Cat izi = (Cat) sess.load(Cat.class, id); izi.setName(iznizi); // might return stale data sess.find("from Cat as cat left outer join cat.kittens kitten"); // change to izi is not flushed! ... tx.commit(); // flush occurs sess.close();
在刷新期间,可能会发生异常 (例如,如果DML操作违反了 约束)。自处理异常以来 涉及到一些了解 Hibernate的事务行为,我们 在第11章,交易中讨论它 和并发。
因此,如上所述并在代码段中显示,请尝试使用FlushMode.COMMIT
。
请注意,如果您使用identity
生成器,这将无济于事,Hibernate将在save
时写入数据库。
另请注意,FlushMode
的{{1}}只是提示,但行为并未得到严格保证。