0

我正在使用基于 Hibernate 3.6.10 的 JPA2.0 ,我创建了两个多对多关系的对象。

@Entity
@Table(name="Project")
public class Project implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    private String topic;
    @Lob
    @Basic(fetch=FetchType.LAZY)
    private String content;
    @ManyToMany(fetch=FetchType.EAGER)
    @JoinTable(name="TrProj_Area",joinColumns=@JoinColumn(name="TrProj_ID"), inverseJoinColumns=@JoinColumn(name="Area_ID"))
    private Set<Area> areas = new HashSet<Area>();
    //getters and setters
}

@Entity
@Table(name="Area")
public class Area implements Serializable{
     @Id
     @GeneratedValue(strategy = GenerationType.AUTO)
     private Integer id;
     private String name;
     @ManyToMany(mappedBy="areas")
     private Set<Project> projects;
     //getters and setters
}

Project实体有一个content属性,它是LobLazy Fetch,当我创建这样的查询时:

select distinct o from Project o join o.areas a where a.id in(?,?)

它在 MySQL 5.5 上运行良好,但 SQLServer 2005 没有。SQLServer 错误日志如下:

Error code 306, SQL state S0001: The text, ntext, and image data types cannot be compared or sorted, except when using IS NULL or LIKE operator

我知道这个问题是由内容属性引起的,似乎延迟获取配置不起作用,文本列不能包含在select distinct语句中,但我无法从我的实体中删除它,我该如何解决这个问题?


添加于 20120722

我已经在休眠中跟踪 MySQL(mysql-connector-java-5.1.10-bin.jar 作为驱动程序)生成的 SQL,如下所示:

Hibernate: 
select
    distinct proj0_.id as id1_,
    proj0_.content as content1_,
    proj0_.topic as topic1_,
  from
    Project proj0_ 
inner join
    Proj_Area areas1_ 
        on proj0_.id=areas1_.Proj_ID 
inner join
    Area area2_ 
        on areas1_.Area_ID=area2_.id 
where
    area2_.id in (
            ? , ?
        )
order by
    proj0_.id desc limit ?

这是由SQLServer2005(sqljdbc4.jar作为驱动程序)生成的,我担心错误是由group by语句引起的

Hibernate: 
    WITH query AS (select
        ROW_NUMBER() OVER (
    order by
       proj0_.id desc) as __hibernate_row_nr__,
       proj0_.id as id1_,
       proj0_.content as content1_,
       proj0_.topic as topic1_,
    from
       project proj0_ 
    inner join
       proj_area areas1_ 
           on proj0_.id=areas1_.proj_id 
    inner join
       area area2_ 
           on areas1_.area_id=area2_.id 
    where
       area2_.id in (? , ?)) 
    group by
        proj0_.id,
        proj0_.content,
        proj0_.topic) SELECT
        * 
    FROM
        query 
    WHERE
        __hibernate_row_nr__ BETWEEN ? AND ?
4

2 回答 2

2

解决方法是使用子查询来选择不同的 id 值集并使用它来限制返回的值。它之所以有效,是因为将 distinct 应用于除 id 之外的任何东西都是多余的。

SELECT b 
FROM Project b 
WHERE b.id IN(SELECT distinct o.id 
              FROM Project o join o.areas a 
              WHERE a.id IN(?,?))
于 2012-07-21T16:42:24.003 回答
0

正如JB Nizet所说,并参考http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#performance-fetching-lazyproperties。那是因为fetch lazyproperties功能不起作用。根据该文件,有两种解决方案。最后,我选择了文档所写的首选解决方案。

至少对于只读事务而言,避免不必要的列读取的另一种方法是使用 HQL 或 Criteria 查询的投影功能。这避免了构建时字节码处理的需要,当然是首选的解决方案。

还有一些解释。@Basic(fetch = FetchType.LAZY) 不起作用?

于 2012-07-22T09:47:06.463 回答