我打算为那些非容器管理的客户端(如JRX-RS资源)编写业务方法。
@Stateless
public class PersistenceService {
public <R> R apply(final Function<EntityManager, R> function) {
return function.apply(entityManager);
}
@PersistenceContext
private transient EntityManager entityManager;
}
这样JAX-RS根资源类就像这样使用它。
@RequestScoped
@Path("/entities")
public class MyEntites {
@GET
@Path("/{id: \\d+}")
public Response read(final long id) {
return Response.ok(service.apply(m -> {
m.find(MyEntity.class, id);
})).build();
}
@Inject
private transient PersistenceService service;
}
问题是如何阻止客户端在指定的实体管理器上调用close()
?
service.apply(m -> {
m.close();
return null;
});
答案 0 :(得分:1)
您可以围绕原始实体管理器创建一个包装器,以确保永远不会调用close()
:
public class NoCloseEntityManager implements EntityManager {
private EntityManager wrapped;
public NoCloseEntityManager(EntityManager wrapped) {
this.wrapped = wrapped;
}
public void close() {
throw new UnsupportedOperationException("Don't call close()");
}
// all other methods from the interface call the wrapped manager:
public void persist(Object entity) {
wrapped.persist(entity);
}
...
}
您可以在服务中使用:
@Stateless
public class PersistenceService {
@PersistenceContext
private transient EntityManager entityManager;
public <R> R apply(final Function<EntityManager, R> function) {
return function.apply(new NoCloseEntityManager(entityManager));
}
}
但是我不知道结果的努力是否更糟,因为entityManager.close()
并非经常被调用 - 如果有人打电话给他,他就不会错误地使用它...... < / p>
答案 1 :(得分:0)
我为任何人提供了另一种可能的解决方案。
@Stateless
public class PersistenceService {
private static final Method CLOSE;
static {
try {
CLOSE = EntityManager.class.getMethod("close");
} catch (final NoSuchMethodException nsme) {
throw new InstantiationError(nsme.getMessage());
}
}
@PostConstruct
private void constructed() {
entityManager = (EntityManager) Proxy.newProxyInstance(
entityManager_.getClass().getClassLoader(),
new Class<?>[]{EntityManager.class},
(proxy, method, args) -> {
if (CLOSE.equals(method)) {
throw new RuntimeException("i'll find you.");
}
return method.invoke(entityManager_, args);
});
}
@PreDestroy
private void destroying() {
entityManager = null;
}
@PersistenceContext
private transient EntityManager entityManager_;
private transient EntityManager entityManager;
}
现在我可以添加所需的方法。
public <R> R apply(final Function<EntityManager, R> function) {
return function.apply(entityManager);
}
public <U, R> R apply(final BiFunction<EntityManager, U, R> function,
final U u) {
return function.apply(entityManager, u);
}
public int applyAsInt(final ToIntFunction<EntityManager> function) {
return function.applyAsInt(entityManager);
}
public <U> int applyAsInt(final ToIntBiFunction<EntityManager, U> function,
final U u) {
return function.applyAsInt(entityManager, u);
}
public long applyAsLong(final ToLongFunction<EntityManager> function) {
return function.applyAsLong(entityManager);
}
public <U> long applyAsLong(
final ToLongBiFunction<EntityManager, U> function, final U u) {
return function.applyAsLong(entityManager, u);
}
public double applyAsDouble(
final ToDoubleFunction<EntityManager> function) {
return function.applyAsDouble(entityManager);
}
public <U> double applyAsDouble(
final ToDoubleBiFunction<EntityManager, U> function, final U u) {
return function.applyAsDouble(entityManager, u);
}