Tha*_*ham 3 generics crud java-ee ejb-3.0
这个问题曾经在这里被问到过简单CRUD的EJB 3会话Bean设计,我只想更深入地询问有关此设计的问题.我已经尝试在原帖上提问,但是,我没有看到任何回复,所以我决定创建新帖子.因此,实现通用CRUD会话bean的Pascal解决方案如下
public interface GenericCrudService {
public <T> T create(T t);
public <T> T find(Class<T> type, Object id);
public <T> void delete(T t);
public <T> T update(T t);
public List findWithNamedQuery(String queryName);
public List findWithNamedQuery(String queryName, int resultLimit);
public List findWithNamedQuery(String namedQueryName,
Map<String, Object> parameters);
public List findWithNamedQuery(String namedQueryName,
Map<String, Object> parameters,
int resultLimit);
public <T> List<T> findWithNativeQuery(String sql, Class<T> type);
}
Run Code Online (Sandbox Code Playgroud)
和
@Stateless
@Remote(GenericCrudService.class)
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public class GenericCrudServiceBean implements GenericCrudService {
@PersistenceContext
private EntityManager em;
@Override
public <T> T create(T t) {
em.persist(t);
return t;
}
@Override
public <T> T find(Class<T> type, Object id) {
return em.find(type, id);
}
@Override
public <T> void delete(T t) {
t = em.merge(t);
em.remove(t);
}
@Override
public <T> T update(T t) {
return em.merge(t);
}
@Override
public List findWithNamedQuery(String queryName) {
return em.createNamedQuery(queryName).getResultList();
}
@Override
public List findWithNamedQuery(String queryName, int resultLimit) {
return em.createNamedQuery(queryName).setMaxResults(resultLimit)
.getResultList();
}
@Override
public List findWithNamedQuery(String namedQueryName,
Map<String, Object> parameters) {
return findWithNamedQuery(namedQueryName, parameters, 0);
}
@Override
public List findWithNamedQuery(String namedQueryName,
Map<String, Object> parameters,
int resultLimit) {
Query query = this.em.createNamedQuery(namedQueryName);
if(resultLimit > 0) {
query.setMaxResults(resultLimit);
}
for (Map.Entry<String, Object> entry : parameters.entrySet()) {
query.setParameter(entry.getKey(), entry.getValue());
}
return query.getResultList();
}
@Override
@SuppressWarnings("unchecked")
public <T> List<T> findWithNativeQuery(String sql, Class<T> type) {
return em.createNativeQuery(sql, type).getResultList();
}
}
Run Code Online (Sandbox Code Playgroud)
问题:
1)当我尝试在我的托管bean中引用这个EJB bean时,我必须这样做
@EJB
private GenericCrudService myEJB;
Run Code Online (Sandbox Code Playgroud)
代替
@EJB
private GenericCrudServiceBean myEJB;
Run Code Online (Sandbox Code Playgroud)
这对我来说没什么意义,因为GenericCrudService它只是一个接口,GenericCrudServiceBean是无状态Bean
当我这样做时GenericCrudServiceBean,我得到了这个例外
Caused by: javax.naming.NamingException: Lookup failed for 'java:comp/env/com.bridgeye.web.Profile/myEJB' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=com.bridgeye.web.Profile/myEJB,Remote 3.x interface =com.bridgeye.ejb.GenericCRUDServiceBean,ejb-link=null,lookup=,mappedName=,jndi-name=com.bridgeye.ejb.GenericCRUDServiceBean,refType=Session' . Actual (possibly internal) Remote JNDI name used for lookup is 'com.bridgeye.ejb.GenericCRUDServiceBean#com.bridgeye.ejb.GenericCRUDServiceBean' [Root exception is javax.naming.NamingException: Lookup failed for 'com.bridgeye.ejb.GenericCRUDServiceBean#com.bridgeye.ejb.GenericCRUDServiceBean' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: com.bridgeye.ejb.GenericCRUDServiceBean#com.bridgeye.ejb.GenericCRUDServiceBean not found]]]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:518)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:597)
Run Code Online (Sandbox Code Playgroud)
2)javax.rmi.Remote和javax.ejb.Remote之间的区别是什么?如果我拿出注释Remote,我的EJB是否变为本地,或者我必须使用注释Local指定
3)在我的托管bean中,我做了一个简单的myEJB.find(User.class, id),但如果我有@TransactionAttribute(TransactionAttributeType.MANDATORY),那么我遇到异常,如果我拿出TransactionAttribute声明,它工作正常.知道为什么吗?
javax.ejb.Remote是一个EJB 3.0注释,java.rmi.Remote而是一个来自EJB存在之前的简单接口.没有javax.rmi.Remote.你是对的,如果你不使用Remote注释,那么默认情况下EJB将被认为只有一个本地接口.来自API doc TransactionAttributeType.MANDATORY:
如果客户端在客户端与事务上下文关联时调用企业bean的方法,则容器将在客户端的事务上下文中调用企业bean的方法.
如果没有现有事务,则抛出异常.
您可能希望使用TransactionAttributeType.REQUIRED,如果不存在则会自动启动事务,如果您使用不带参数的注释,则也是默认值.