【问题标题】:JPA MEMBER OF Query with detached EntityJPA MEMBER OF Query with detached Entity
【发布时间】:2012-02-02 11:42:46
【问题描述】:

我想做一个简单的 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 对象作为查询参数时,相同的查询会起作用。 “标签”参数真的必须是托管实体吗?为什么?我怎样才能让查询工作?谢谢大家的帮助!

[编辑:] 谢谢你的提示。我现在结束了这个查询:

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;
}

【问题讨论】:

    标签: hibernate jpa orm jpa-2.0


    【解决方案1】:

    正如 Nayan Wadekar 所说,:memberParameter MEMBER OF i.tags 需要一个持久实例。

    所以这里有两种解决方法。

    1. 确保传入一个已经持久化的标记对象实例。
    2. 如果您不能这样做,您可以通过 JOIN 查询通过“标签”名称进行查询:

      SELECT i FROM ItemDescription i JOIN c.tags t
      WHERE t.name LIKE :name
      

    【讨论】:

      【解决方案2】:

      当事务提交时,持久化上下文中的所有对象都与底层数据库同步。因此,当您设置实体管理器检索的对象时工作正常,因为对象处于托管状态。

      在这里,您正在创建一个新对象并将其设置为事务中查询的参数,导致对象分离时出现异常。

      来自文档:

      当用户将瞬态实例传递给 Session 方法时抛出 需要一个持久实例。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-27
      • 1970-01-01
      • 1970-01-01
      • 2022-12-01
      • 2011-02-10
      • 2017-08-21
      • 1970-01-01
      • 2013-08-23
      相关资源
      最近更新 更多