【问题标题】:Entity using entity manager , how good is this design?Entity 使用 entity manager ,这个设计有多好?
【发布时间】:2012-12-27 19:24:49
【问题描述】:

我正在评估这种允许实体访问实体管理器的设计。

图书实体:

@Entity
public class Book implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private Long isbn;
    private String nom;

     public void save() {
        System.out.println("OWN PERSIST !");
      **ThreadLocalEntityManager.em().persist(this);**
    }
}

图书服务:

@Stateless
@Interceptors(EntityManagerInjector.class)

public class BookService {
       public void create()
       {
         Book b=new Book(1,2,"3");
         b.save();
       }
}

EntityManagerInjector

public class EntityManagerInjector implements Serializable {

    @PersistenceContext
    private EntityManager em;

    @AroundInvoke
    public Object associate(InvocationContext ic) throws Exception {
        ThreadLocalEntityManager.associateWithThread(em); //statically imported method
        try {
            return ic.proceed();
        } finally {
            ThreadLocalEntityManager.cleanupThread();
        }
    }
}

ThreadLocalEntityManager

public class ThreadLocalEntityManager {

    private static final ThreadLocal<EntityManager> THREAD_WITH_EM = new ThreadLocal<EntityManager>();

    private ThreadLocalEntityManager() {
    }

    public static void associateWithThread(EntityManager em) {
        THREAD_WITH_EM.set(em);
    }

    public static EntityManager em() {
        System.out.println("gettint entitymanger from thread:"+THREAD_WITH_EM.toString());
        System.out.println("entitymanger id:"+THREAD_WITH_EM.get().toString());
        return THREAD_WITH_EM.get();
    }

    public static void cleanupThread() {
        THREAD_WITH_EM.remove();
    }
}

我有一些问题:

  1. 这是避免使用 crud 服务(创建、删除、findXX)的好设计吗?
  2. 此设计能否在 容器?
  3. book.save() 声明更改为静态是简化对“持久性操作”的访问的好方法(避免新的Book().find(id)" 吗?

谢谢。 ps1:我正在使用JPA 2Ejb 3.1 和 Glassfish 3.1.2

ps2:我在 Real World Java EE Patterns Rethinking Best Practices (Adam Bien) 中发现了这个设计

【问题讨论】:

    标签: design-patterns jakarta-ee jpa ejb jpa-2.0


    【解决方案1】:

    我会反对这种设计。

    1. 大多数应用服务器不喜欢你修补线程

      App Server 为处理请求做了很多近乎神奇的线程管理,强烈建议您甚至不要在 JavaEE 中创建线程。

    2. EntityManager 是短暂的东西

      一个 EM 应该只在交易持续的时候存活。在这种情况下,看起来 EM 可以传递到在同一个容器中运行的不同应用程序中。这可以使调试成为一种真正的乐趣。

      想象一下,如果您从 BookService 调用不同的 EJB,它会将 EM 设置为另一个 EJB 的 EM。如果您有两个持久性单元,这将是一个大问题。

    3. 不开放扩展

      该系统中的任何新 EJB 都必须了解这种处理 EM 的有趣方式。如果您是编写它们的人,这没关系,但是外部提供的 EJB 呢?

    4. 缺乏凝聚力

      EJB 是控制/定义事务的地方。为什么我们要推出 JPA bean 的接口? save() 只能在这个非常具体的框架内工作,并且在单元测试中将是 100% 的痛苦。

      想一想,如果你想重新使用这个 bean 来做一些需要 XML 序列化的事情,比如 WebServices。现在save() 不能正常工作。持久化引擎已经可以通用地处理 bean,不要在它上面写另一个层来剥离它。

    【讨论】:

      猜你喜欢
      • 2019-08-16
      • 2015-11-10
      • 1970-01-01
      • 2014-09-30
      • 2015-02-26
      • 1970-01-01
      • 2013-08-05
      • 2015-06-27
      • 2011-06-18
      相关资源
      最近更新 更多