4

我是休眠的新手。我有一个问题,当我尝试运行选择查询时说

"from Foo where Foo.some_id=2"

(使用 Hibernate 模板)然后 Hibernate 还尝试将记录插入到与 Foo 表具有一对一关联的表 'Foo2' 中

豆豆

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>
...

豆豆2

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
4

1 回答 1

5

我的猜测是您在会话中有待处理的更改(一些 Foo2 实例等待插入),并且默认情况下,Hibernate 在运行查询之前刷新会话以提供非陈旧结果。这在文档的以下部分中进行了解释:

10.10。刷新会话

有时 Session 会执行同步 JDBC 连接状态和内存中对象状态所需的 SQL 语句。此过程称为刷新,默认情况下发生在以下几点:

  • 在一些查询执行之前
  • 来自 org.hibernate.Transaction.commit()
  • 从 Session.flush()

SQL 语句按以下顺序发出:

  1. 所有实体插入以相同的顺序保存相应的对象Session.save()
  2. 所有实体更新
  3. 所有集合删除
  4. 所有集合元素的删除、更新和插入
  5. 所有集合插入
  6. 所有实体删除以相同的顺序删除相应的对象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只是对 的提示Session行为并未得到严格保证。

于 2010-10-10T19:17:42.747 回答