如何将Spring实体传递给泛型超类?附泛型超类实现代码
如何将Spring实体传递给泛型超类RootQueryCreator?
我来给你梳理几种可行的实现方式,帮你把Spring实体传递给这个泛型超类:
1. 创建具体子类并通过构造函数传递实体
因为Spring无法直接实例化泛型类,你需要为每个实体创建对应的子类,明确指定泛型参数,然后在子类构造中传入实体实例:
首先定义你的Spring实体(比如User):
@Entity public class User { // 实体字段、getter/setter 及 JPA 注解 }
然后创建继承自RootQueryCreator的子类,在构造函数中调用父类的带参构造传递实体:
@Repository public class UserQueryCreator extends RootQueryCreator<User> { public UserQueryCreator() { super(new User()); // 传递User实体实例给父类 } }
这样Spring会自动扫描这个子类并创建Bean,同时父类的entity字段会被正确赋值,后续initRootQuery方法也能基于该实体构建查询。
2. 通过配置类手动创建Bean实例
如果你不想为每个实体都写子类,可以在Spring配置类中直接创建泛型超类的实例,指定具体实体类型并传递实体:
@Configuration public class QueryCreatorConfig { @PersistenceContext private EntityManager em; @Bean public RootQueryCreator<User> userQueryCreator() { RootQueryCreator<User> creator = new RootQueryCreator<>(new User()); // 因为父类的em是@PersistenceContext注入,Spring会自动为这个Bean注入EntityManager return creator; } // 其他实体的QueryCreator Bean同理 @Bean public RootQueryCreator<Order> orderQueryCreator() { return new RootQueryCreator<>(new Order()); } }
3. 优化:通过反射获取实体类型(替代传递实体实例)
其实你的父类中持有T entity主要是为了获取实体类型,完全可以通过反射获取泛型的实际类型,避免手动传递实体实例。修改父类的初始化逻辑:
@Repository public abstract class RootQueryCreator<T> { @PersistenceContext private EntityManager em; private Class<T> entityClass; CriteriaBuilder criteriaBuilder = null; CriteriaQuery<T> criteriaQuery = null; Root<T> rootTable = null; @PostConstruct public void initRootQuery() { // 通过反射获取泛型实际类型 Type type = getClass().getGenericSuperclass(); ParameterizedType paramType = (ParameterizedType) type; entityClass = (Class<T>) paramType.getActualTypeArguments()[0]; criteriaBuilder = em.getCriteriaBuilder(); criteriaQuery = criteriaBuilder.createQuery(entityClass); rootTable = criteriaQuery.from(entityClass); } }
然后子类只需继承并指定泛型参数即可,无需传递实体实例:
@Repository public class UserQueryCreator extends RootQueryCreator<User> { // 空构造即可 }
这种方式更优雅,避免了手动new实体实例的冗余操作。
内容的提问来源于stack exchange,提问作者Markus Schnee
相关产品推荐
相关产品推荐

