Hibernate: ВЫБРАТЬ в ОБНОВЛЕНИИ - PullRequest
2 голосов
/ 01 октября 2011

Мне нужно сделать что-то подобное:

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 ]

2 голосов
/ 03 октября 2011

Если вы наблюдаете

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

Выбор должен возвращать уникальное значение. Если этого не произойдет, то все пойдет не так, потому что вы получаете сет с правой стороны, но с левой стороны ожидается книга.

Это очень похоже на синтаксис sql.

1 голос
/ 01 октября 2011

Не знаю, может ли это вам помочь, я только что копался в 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, этот запрос будет выполненуспешно, иначе это не получится.

Надеюсь, это поможет.

0 голосов
/ 01 октября 2011

Попробуйте это - обратите внимание на макс. Без этого hibernate не сможет узнать, что внутренний запрос вернет только одну строку.

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