繁体   English   中英

JPA - 渴望 - 懒惰的最佳实践

[英]JPA - Eager - Lazy best practice

JBoss EAP 6
休眠4

我有一个带有Web浏览器客户端的J2EE应用程序。 (Apache单击)内部业务逻辑和客户端都使用相同的实体对象。

我想将实体中的所有关系设置为延迟加载。 这样我的表现很好。

但是当使用客户端中的实体(即apache click的服务器端代码)时,我需要很多关系才能加载。 客户端代码通过会话bean访问后端。

所以我有几种方法可以解决这个问题:

  1. 创建每个JPA实体中的两个,一个具有预先加载,一个具有延迟加载。 然后使用客户端中急切加载的那个,以及服务器中延迟加载的那个。 大多数服务器逻辑都在一个事务中,所以延迟加载就好了。

  2. 使所有关系延迟加载。 从客户端访问实体时,请确保存在事务。 (@TransactionAttribute(TransactionAttributeType.REQUIRED))并编写对必要字段的访问权限,以便在会话bean调用后可以访问它们。 但这意味着我必须在不需要时启动事务,即如果我只获取某些对象。 我必须维护更多代码。 而且我必须确切地知道客户需要什么样的关系。

  3. 创建一个继承层次结构,其中我有一个超级实体,然后是2个子节点,一个具有延迟加载的对象关系,另一个只有值,没有对象。 即:

    @MappedSuperclass
    public class SuperOrder {

    @Id
    @Column(name = "id")
    @GeneratedValue(.....)
    private Long id;

    @Column(name = "invoice", length = 100)
    private String invoice;

孩子1

    @Entity
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @Table(name = "testorder")
    @SequenceGenerator(....)
    public class Order extends SuperOrder {

    @ManyToOne(targetEntity = PrintCustomerEnt.class, fetch = FetchType.EAGER, optional = true)
    @JoinColumn(name = "print_customer_id", nullable = true)
    @ForeignKey(name = "fk_print_customer")
    @Valid
    private PrintCustomerEnt printCustomer;

    public PrintCustomerEnt getPrintCustomer() {
        return printCustomer;
    }

    public void setPrintCustomer(final PrintCustomerEnt printCustomer) {
        this.printCustomer = printCustomer;
    }

    }

孩子2

    @Entity
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @Table(name = "testorder")
    @SequenceGenerator(...)
    public class LazyOrder extends SuperOrder {

    @Transient
    private String printCustomerName;

    @Column(name = "print_customer_id", nullable = true)
    private Long printCustomerId;

什么是最佳实践...或者还有其他好的方法可以做到这一点。

基本上问题是我想在不同的场景中使用相同的实体。 有时我需要急切加载,有时我需要延迟加载。

我建议您只创建一个具有延迟关系的JPA实体,当您需要急切加载其中一些时,创建一个使用JPQL(HQL)来执行某些FETCH技巧的服务。 这个想法是一个JPA实体和许多服务。

我已经在JPA 2中编程了一段时间了,我可以说现在有一些我几乎总是适用的书面规则:

  1. 在所有OneToMany,ManyToMany关系中使用LAZY Inicialization
  2. 在所有OneToOne,ManyToOne关系上使用EAGER Inicalization

此规则适用于99%的项目。 我认为这些都是最佳实践,因为我的个人经验和我一直在做的一些研究。

注意:我必须说我不在Lazy Inicialization上使用JOIN FETCH,而是编写预取方法。 例:

@Entity
class Entity{
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Basic(optional = false)
  private Integer id;

  @OneToMany(cascade = CascadeType.ALL, mappedBy = "mappedName",
        orphanRemoval = true)
  private List<Child1> collection1;

  @OneToMany(cascade = CascadeType.ALL, mappedBy = "mappedName",
        orphanRemoval = true)
  private List<Child2> collection2;  }

然后我们有控制器:

class EntityController{

  public Entity findCompraFolioFull(Integer id) {
    EntityManager em = getEntityManager();
    try {
        Entity entity =  em.find(Entity.class, id);
        //Initialize Collections inside Transaccion, this prevents
        //LazyInizialization No Proxy Exception later in code when calling
        //hollow collections
        cp.getCollection().size();
        cp.getCollection().size();
        return cp;
    } finally {
        em.close();
    }
  } 
}

我不推荐FETCH JOIN

 public Entity findEntityByJoinFetch(Integer id) {
    EntityManager em = getEntityManager();
    try {
        TypedQuery<Entity> tq = em.createQuery(
                "SELECT e FROM Entity e\n"
                        + "LEFT JOIN FETCH e.collection1\n"
                        + "LEFT JOIN FETCH  e.collection2\n"
                        + "WHERE e.id = :id", Entity.class);
        tq.setParameter("id", id); 
        return tq.getSingleResult();
    } finally {
        em.close();
    }
}

我不推荐Fetch Join Appoach的原因:

  • 如果你的集合是java.util.List类型,那么这个getSingleResult()将在hibernate中失败,因为缺少获取MultipleBags的能力而没有在OneToMany Relation上编制索引符号。

  • 您总是可以将集合的类型更改为java.util.set,以便获取多个行李,但这会带来新的情况,Set不是有序的,HashCode()方法也无法正常工作所以你必须在Children Classes中@Override它,如果你使用JAVAFX TableView将模型绑定到Items,你将无法绑定集合Set Type到ItemView的Item属性,至少不是直接。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM