Hibernate:UPDATE中的SELECT

时间:2011-10-01 12:06:03

标签: java hibernate select hql

我需要做类似的事情:

session.getTransaction().begin();
session.createQuery("update Pack p set p.book = (select b from Book b where ...) where p.id = :id")
        .setLong("id", pack.getId())
        .executeUpdate();
session.getTransaction().commit();

有错误:

Exception occurred during event dispatching: 
org.hibernate.TypeMismatchException: left and right hand sides of a binary logic operator were incompatibile [java.util.Set(BookKeeper.db.Pack.book) : BookKeeper.db.Book]

但为什么呢? p.book具有Set<Book>类型,与(select b from Book b where ...)必须返回相同。

3 个答案:

答案 0 :(得分:2)

如果你观察

p.book = (select b from Book b where ...)

select应返回唯一值。如果没有,那么事情就会出错,因为你在右手边有一套,但是左手边有一本书。

这与sql语法非常相似。

答案 1 :(得分:1)

我不知道它是否对你有所帮助,我只是深入研究了Hibernate源代码。

您的异常发生在BinaryLogicOperatorNode.java中 在以下地方:

if ( lhsColumnSpan != rhsType.getColumnSpan( sessionFactory ) ) {
        throw new TypeMismatchException(
  "left and right hand sides of a binary logic operator were incompatibile [" +
   lhsType.getName() + " : "+ rhsType.getName() + "]"
   );

当rhsType和lhsType是org.hibernate.Type对象时:

Type lhsType = extractDataType( lhs );
Type rhsType = extractDataType( rhs );

现在让我们看看getColumnSpan()正在做什么:

根据Hibernate文档:

public int getColumnSpan(Mapping mapping) throws MappingException
How many columns are used to persist this type.

因此,根据此逻辑,您只能在相同大小的对象上运行此类查询:

如果Set<Book> p.bookselect b from Book b返回的对象数量相同,则此查询将成功运行,否则会失败。

希望它有所帮助。

答案 2 :(得分:0)

试试这个 - 注意最大值。没有它,hibernate就无法知道内部查询只会返回一行。

update Pack p set p.book = (select max(b) from Book b where ...) where p.id = :id