【问题标题】:JPA/Hibernate Join and Fetch single columnJPA/Hibernate Join 和 Fetch 单列
【发布时间】:2012-08-31 21:35:17
【问题描述】:

我是 JPA/Hibernate 的新手。假设我有这两张表:

  • Employee (Id, Name, DeptId, ..) // DeptId 是外键。
  • Department (Id, DeptName, ..) // 部门单独保留

以及以下实体:

@Entity
public class Employee {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    private String name;
    private long salary;

    @OneToOne(cascade = {CascadeType.PERSIST})
    @JoinColumn(name="DEPT_ID") 
    private Dept dept;
    ...
    }

@Entity
public class Dept {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    private String name;
    ...
    **other huge collections with eager fetch ***
    }

在我的应用程序 DAO 中,每当我访问 Employee 实体时,我只需要将部门名称作为员工实体的一部分,而不需要部门表中的其他任何内容。

  1. 如何获取部门。仅名称列而不是员工实体中的整个部门行(需要避免急于获取部门收集的大量数据)?如果是,我应该使用哪些注释?
  2. 在这种情况下如何处理级联?

【问题讨论】:

    标签: hibernate jpa


    【解决方案1】:

    最好的选择是使集合延迟加载,然后将需要集合的查询更改为预加载(使用连接提取)。如果您有充分的理由不这样做,那么您可以尝试以下解决方法。

    您可以使用投影查询。这将为每个结果生成一个 [employee,name] 数组。

    select employee, employee.dept.name from Employee employee
    

    您可以使用@Formula 将 Employee 表中的属性映射到 Department 表中的列(请注意,此解决方案是 Hibernate 特定的)

    class Employee {
    
       @Formula("(select deptName from Department where Department.id = DEPT_ID)"
       String deptName;
    
    } 
    

    另一种选择是创建一个没有集合的新类 DeptLite。将其映射为只读 - @org.hibernate.annotations.Entity(mutable=false)

    @Entity
    public class Employee {
    
        @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
        private int id;
        private String name;
        private long salary;
    
        @OneToOne(cascade = {CascadeType.PERSIST})
        @JoinColumn(name="DEPT_ID") 
        private Dept dept;
    
        @OneToOne(updatable=false,insertable=false)
        @JoinColumn(name="DEPT_ID") 
        private DeptLite deptLite;
    
        ...
    }
    
    @Entity
    @org.hibernate.annotations.Entity(mutable=false)
    class DeptLite  {
    
    }
    

    【讨论】:

    • 谢谢。如果我选择最好的选择(使集合延迟加载并使用 onone 映射的情况),那么在插入/保存的情况下会发生什么?我是否需要先查询部门表以获取部门对象,然后将其用于插入到员工表中?
    • 您可以使用 entityManger.getReference(Dept.class,id) (用于休眠 session.load()),这将创建一个带有 id 的代理,然后可以在 Employee 上设置该代理。这样您就可以插入新员工,而无需从 db 加载部门详细信息。如果您有部门 ID,则此方法有效 - 如果您只有部门名称,则需要查询部门对象。
    • 如果它回答了您的问题 - 请接受它meta.stackexchange.com/questions/5234/…
    【解决方案2】:

    如果您想要限制实体中加载的属性,我认为有两种方法可以实现:

    1. 使用lazy property fetching,并在模型中注释您不想在每次检索实体时加载的属性。

    2. 使用 Hibernate Projections 并限制您在每个查询中需要哪些属性,为每个属性添加一个 PropertyProjection。像这样的:

      Projections.projectionList().add(Projections.property("prop1")).add(Projections.property("prop2")).. 
      

    希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-30
      • 2020-11-10
      • 2021-12-19
      • 2015-07-31
      • 1970-01-01
      • 2017-08-10
      • 2011-10-13
      • 2010-10-07
      相关资源
      最近更新 更多