我需要做类似的事情:
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 ...)
必须返回相同。
答案 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.book
与select b from Book b
返回的对象数量相同,则此查询将成功运行,否则会失败。
希望它有所帮助。
答案 2 :(得分:0)
试试这个 - 注意最大值。没有它,hibernate就无法知道内部查询只会返回一行。
update Pack p set p.book = (select max(b) from Book b where ...) where p.id = :id