代码之家  ›  专栏  ›  技术社区  ›  RMorrisey

使用休眠注释的视图对象的错误SQL

  •  1
  • RMorrisey  · 技术社区  · 15 年前

    我正在为数据库视图处理Hibernate实体映射;当我对其执行条件查询时,Hibernate正在生成错误的SQL。如果能帮我弄清楚我的地图有什么问题,我将不胜感激!

    我有两个正在试图从数据库视图中获取的映射实体;该视图没有其他列,只有每个实体的fk。其中一个FK可以被视为主键,因为视图为每个主要实体都有一行。因此,视图的数据库架构如下:

    primary(primary_id, some_other_fields)
    history(history_id, primary_id, some_other_fields)
    view_latest_status_history(primary_id, history_id)
    

    注意,使用该视图是因为我只想为每个主记录挑选最新的历史记录,而不是所有映射的历史记录。这是我用于视图的对象,带有实体注释:

    @Entity
    @org.hibernate.annotations.Entity(dynamicUpdate = true)
    @Table(name = "view_latest_status_history")
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    public class ViewLatestStatusHistoryRow implements Serializable {
        private Primary primary;
        private History history;
    
        /**
         * @return Returns the history.
         */
        @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.LAZY)
        @JoinColumn(name = "history_id", nullable = true)
        @AccessType("field")
        public History getHistory() {
            return history;
        }
    
        //equals() and hashCode() implementations are omitted
    
        /**
         * @return Returns the primary.
         */
        @Id
        @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, fetch = FetchType.LAZY)
        @JoinColumn(name = "primary_id", nullable = false)
        @AccessType("field")
        public Primary getPrimary() {
            return primary;
        }
    }
    

    主对象和历史对象都有完整的工作实体注释。

    我的条件设置:

    criteria.add(Restrictions.in("primary", [collection of primary objects]));
    criteria.setFetchMode("primary", FetchMode.JOIN);
    criteria.setFetchMode("history", FetchMode.JOIN);
    

    以及(错误的)生成的SQL:

    select this_.primary as primary78_1_, this_.primary_id as prim2_78_1_, primary2_.history_id as unique1_56_0_, ...history fields
    from DB_CATALOG.dbo.view_latest_status_history this_ 
    left outer join DB_CATALOG.dbo.history primary2_ on this_.primary_id=primary2_.primary_id 
    where this_.specChange in (?, ?...)
    

    在编辑我们项目的db模式的细节时,我可能会弄乱一些东西,但重点是“select”子句中的第一个字段是错误的:

    这个主字段(view_latest_status_history.primary)不是字段;该字段应该称为主字段。我认为这可能与主字段上的@id注释有关?有什么解决办法吗?如果删除@id,则会收到一个错误,告诉我该实体没有主键。

    更新:

    我不再使用联接表表示法(如下建议)将视图映射为字段。注释修改如下。此解决方案在HQL中正常工作,并在启用hbm2ddl时生成预期的模式,但我没有使用条件查询对其进行重新测试。

    @Entity
    @Table(name = "view_latest_status_history")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    public class ViewLatestStatusHistoryRow implements Serializable {
        private String id;
        private Primary primary;
        private History history;
    
        /**
         * @return Returns the history.
         */
        @OneToOne(optional = true)
        @JoinColumn(name = "history_id", nullable = true)
        @AccessType("field")
        public History getHistory() {
            return history;
        }
    
        //equals() and hashCode() implementations are omitted
    
        @Id
        @Column(name = "primary_id", nullable = false)
        @Override
        @AccessType(value = "field")
        public String getId() {
            return id;
        }
    
        /**
         * @return Returns the primary.
         */
        @PrimaryKeyJoinColumn(name = "primary_id", referencedColumnName = "unique_id")
        @OneToOne(optional = false)
        @AccessType("field")
        public Primary getPrimary() {
            return primary;
        }
    }
    
    1 回复  |  直到 14 年前
        1
  •  1
  •   ChssPly76    15 年前

    最肯定的原因是 @Id 注释-在这种情况下,主键不是主键。实际上,@id和@manytoone也不能在同一个属性上。

    我来问你这个-你为什么要绘制地图 ViewLatestStatusHistoryRow 作为一个实体开始?你不会坚持下去的。考虑将最新的历史记录条目直接(以只读方式)映射到主(多到一)上,并将视图用作联接表。