You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java EE中EJB注入通用CRUD DAO后无法访问方法的问题咨询

解决泛型CRUD抽象类注入后无法访问通用方法的问题

看起来你遇到的核心问题是接口继承关系没理顺——你的ICategoryDaoRemote没有继承通用的IGenericDaoRemote<Category>,导致注入后没法调用通用CRUD方法。咱们一步步来修复:

1. 让实体DAO接口继承通用远程/本地接口

首先修改你的ICategoryDaoRemote,让它继承IGenericDaoRemote<Category>,这样它会自动继承所有通用CRUD方法:

public interface ICategoryDaoRemote extends IGenericDaoRemote<Category> {
    // 这里可以添加Category专属的DAO方法(如果需要的话)
}

同样,本地接口也要对应继承:

public interface ICategoryDaoLocal extends IGenericDaoLocal<Category> {
    // 专属方法写在这里
}

2. 确认DAO实现类的结构(无需修改)

你的CategoryDao已经正确继承了GenericDao<Category>并实现了上述两个接口,这部分是没问题的:

@Stateless
@Remote(ICategoryDaoRemote.class)
@Local(ICategoryDaoLocal.class)
public class CategoryDao extends GenericDao<Category> implements ICategoryDaoRemote, ICategoryDaoLocal {
    // 不需要重复实现通用方法,抽象类GenericDao已经帮你搞定了
}

3. Service层现在可以正常调用通用方法了

现在你在CategoryService里注入ICategoryDaoRemote后,就能直接调用add/remove/update/getAll这些通用方法,同时也能调用Category专属的DAO方法(如果定义了的话):

@Stateless
@Local(ICategoryServiceLocal.class)
@Remote(ICategoryServiceRemote.class)
public class CategoryService implements ICategoryServiceRemote, ICategoryServiceLocal {
    @EJB
    private ICategoryDaoRemote categoryDao;

    public void addCategory(Category category) {
        categoryDao.add(category); // 现在可以正常调用了!
    }

    public List<Category> getAllCategories() {
        return categoryDao.getAll(Category.class);
    }
}

额外优化:简化getAll方法的调用

你可能注意到getAll方法需要传入Class<T>参数,这是因为Java泛型的类型擦除机制。可以通过在抽象类里传入实体类型来简化:

修改GenericDao,添加构造函数接收实体类型:

public abstract class GenericDao<T> implements IGenericDaoLocal<T>, IGenericDaoRemote<T> {
    @PersistenceContext(name = "postgresPersistant")
    private EntityManager entityManager;
    private final Class<T> entityClass;

    // 子类必须调用该构造函数传入实体类
    protected GenericDao(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    @Override
    public void add(T t) {
        Session session = entityManager.unwrap(Session.class);
        session.save(t);
    }

    @Override
    public void remove(T t) {
        Session session = entityManager.unwrap(Session.class);
        session.delete(t);
    }

    @Override
    public void update(T t) {
        Session session = entityManager.unwrap(Session.class);
        session.update(t);
    }

    // 优化后的getAll,无需传参
    @Override
    public List<T> getAll() {
        Session session = entityManager.unwrap(Session.class);
        Criteria criteria = session.createCriteria(entityClass).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        return criteria.list();
    }
}

然后修改CategoryDao的构造函数:

public class CategoryDao extends GenericDao<Category> implements ICategoryDaoRemote, ICategoryDaoLocal {
    public CategoryDao() {
        super(Category.class);
    }
}

对应的通用接口也要更新getAll方法的签名:

public interface IGenericDaoRemote<T> {
    void add(T t);
    void remove(T t);
    void update(T t);
    List<T> getAll(); // 去掉Class<T>参数
}

这样Service层调用就更简洁了:

public List<Category> getAllCategories() {
    return categoryDao.getAll();
}

内容的提问来源于stack exchange,提问作者Suule

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:07:39