1

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

图书实体:

@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) 中找到了这个设计

4

1 回答 1

4

我会反对这种设计。

  1. 大多数 App Server 不喜欢你修补 Thread

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

  2. EntityManagers 是短暂的东西

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

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

  3. 不开放扩展

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

  4. 缺乏凝聚力

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

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

于 2012-12-28T01:34:27.320 回答