开发者

Hibernate: SELECT in UPDATE

I need do something like that:

session.getTransaction().be开发者_开发百科gin();
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();

And have error:

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]

But why? p.book have a Set<Book> type, same as (select b from Book b where ...) must return.


If you observe

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

The select should return a unique value. If it doesn't then things will go wrong, because you get a Set on right hand side but the left hand side is expecting a book.

This is very similar to sql syntax.


I don't know if it might help you, I just digged in Hibernate Source code.

Your exception occurs inside of BinaryLogicOperatorNode.java on the following place:

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

when rhsType and lhsType are the org.hibernate.Type objects:

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

now let's see what getColumnSpan() is doing:

According to Hibernate docs:

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

So according to this logic you can run such type of queries only on equal size objects:

if your Set<Book> p.book has the same amount of objects as select b from Book b returns, this query would run successfully, otherwise it would fail.

Hope it helps.


Try this - notice the max. Without that there is no way for hibernate to know that the inner query will only return a single row.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜