JPA MEMBER OF Query с отдельным объектом - PullRequest
2 голосов
/ 04 января 2012

Я хочу сделать простой запрос JPA MEMBER OF, но я не могу заставить его работать. Hibernate генерирует TransientObjectException с сообщением «объект ссылается на несохраненный временный экземпляр - сохраните экземпляр перед сбросом: тег» Запрос выглядит следующим образом:

public Collection<ItemDescription> getItems(){
    String entityClass = "ItemDescription";
    TypedQuery<ItemDescription> query = entityManager.createQuery(
            "SELECT i FROM " + entityClass +" i " +
            "WHERE :tag MEMBER OF i.tags", ItemDescription.class);
    query.setParameter("tag", new Tag("category:test"));
    List<ItemDescription> resultList = query.getResultList();
    return resultList;
}

Два класса сущностей выглядят следующим образом:

@Entity
@Table(name = "tags")
public class Tag extends AbstractDomainEntity {
    private static final long serialVersionUID = 2632379096725992272L;
    private String value;
    ...
}

@Entity
@Table(name = "itemdescriptions")
public class ItemDescription extends AbstractDomainEntity {
    private static final long serialVersionUID = 9164310940207023539L;
    private Set<Tag> tags = new HashSet<Tag>();
    ...
    @OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval = true)
    public Set<Tag> getTags() {
        return tags;
    }
    private void setTags(Set<Tag> tags) {
        this.tags = tags;
    }
}

Тот же запрос работает, когда я использую объект Tag, полученный из диспетчера сущностей, в качестве параметра запроса. Действительно ли параметр «тег» должен быть управляемым объектом? Зачем? Как я могу заставить запрос работать? Спасибо вам, ребята, за помощь!

[EDIT:] Спасибо за ваши советы. Я теперь закончил с этим запросом:

public Collection<ItemDescription> getItems(){
    String entityClass = "ItemDescription";
    TypedQuery<ItemDescription> query = entityManager.createQuery(
            "SELECT i FROM " + entityClass +" i " +
            "JOIN i.tags t " +
            "WHERE t.value = :tag", ItemDescription.class);
    query.setParameter("tag", "category:test");
    List<ItemDescription> resultList = query.getResultList();
    return resultList;
}

Ответы [ 2 ]

1 голос
/ 05 января 2012

Как сказал Найан Вадекар, для :memberParameter MEMBER OF i.tags требуется постоянный экземпляр.

Таким образом, здесь есть два подхода к решению.

  1. Убедитесь, что вы передаете уже постоянный экземпляробъект-тег.
  2. Если вы не можете этого сделать, вы можете выполнить запрос по имени тега через JOIN-запрос:

    SELECT i FROM ItemDescription i JOIN c.tags t
    WHERE t.name LIKE :name
    
1 голос
/ 04 января 2012

Когда транзакция фиксируется, все объекты в контексте постоянства синхронизируются с базовой базой данных.Поэтому, когда вы устанавливаете объект, полученный диспетчером сущностей, работает нормально, поскольку объект находится в управляемом состоянии.

Здесь вы создаете новый объект и устанавливаете его в качестве параметра для запроса в транзакции, результатыв исключительной ситуации, когда объект отсоединен.

Из документации:

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

...