在Spring Data中,当您实现自定义Repository时,由于Java类型擦除的原因,泛型参数T在运行时确实会被擦除为Object类型。不过,有几种方法可以获取实际的类型信息。
你想在自定义的 Spring Data Neo4j Repository 接口中通过默认方法获取泛型 T 的实际类型,这个想法很自然,但遗憾的是,由于 Java 泛型在编译后的"类型擦除"机制,直接在接口的默认方法中可靠地获取 T 的实际类型(Class
Java 的泛型主要在编译阶段提供类型安全检查,编译后泛型类型信息(如 T)会被擦除(除非是继承自泛型父类或实现了泛型接口,且这些泛型类型已被具体化)。在你的 CustomNeo4jRepository
Java 的泛型主要在编译阶段提供类型安全检查,编译后泛型类型信息(如 T)会被擦除(除非是继承自泛型父类或实现了泛型接口,且这些泛型类型已被具体化)。在你的 CustomNeo4jRepository
例如,你希望这样:
public interface CustomNeo4jRepository {
default Class getEntityType() {
// 无法直接在此获取到 UserNode 等具体类型
// 编译后 T 会被擦除为 Object
return ...;
}
}
当 UserRepository 继承 CustomNeo4jRepository
即使尝试通过反射获取泛型信息(如 getClass().getGenericInterfaces()),其结果也取决于接口是如何被继承和代理的。Spring Data 通常会为 Repository 接口创建代理对象,这使得通过反射获取到的泛型信息很可能是 T 本身(一个 TypeVariable
),而非具体的 UserNode 类型,因此难以直接转换为 Class
/**
* 引入个人性仓储
* @author lind
* @date 2025/9/1 14:57
* @since 1.0.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@EnableNeo4jAuditing
@EnableNeo4jRepositories(repositoryBaseClass = CustomNeo4jRepositoryImpl.class)
public @interface EnableNeo4jCustomRepository {
}
/**
* 个性化接口规范
* @author lind
* @date 2025/9/1 14:57
* @since 1.0.0
*/
@NoRepositoryBean // 不让jpa使用代理建立实现类
public interface CustomNeo4jRepository {
/**
* 根据节点名称模糊查询并分页
* @param namePattern 名称模式(如"%知%")
* @param pageable 分页信息
* @return 分页后的节点列表
*/
Page findByNameLike(String namePattern, Pageable pageable);
}
/**
* 个性化接口实现
* @author lind
* @date 2025/9/1 14:57
* @since 1.0.0
*/
public class CustomNeo4jRepositoryImpl extends SimpleNeo4jRepository
implements CustomNeo4jRepository {
private final Neo4jOperations neo4jOperations;
Neo4jEntityInformation entityInformation;
Class domainType;
protected CustomNeo4jRepositoryImpl(Neo4jOperations neo4jOperations,
Neo4jEntityInformation entityInformation) {
super(neo4jOperations,entityInformation);
this.neo4jOperations = neo4jOperations;
this.entityInformation = entityInformation;
this.domainType = entityInformation.getJavaType();
}
@Override
public Page findByNameLike(String namePattern, Pageable pageable) {
String cypherQuery = "MATCH (n:" + domainType.getSimpleName() +
") WHERE n.userName CONTAINS $name RETURN n ORDER BY n.userName SKIP $skip LIMIT $limit";
Map parameters = new HashMap();
parameters.put("name", namePattern.replace("%", ""));
parameters.put("skip", pageable.getOffset());
parameters.put("limit", pageable.getPageSize());
List results = neo4jOperations.findAll(cypherQuery, parameters, domainType);
// 获取总数用于分页
String countQuery = "MATCH (n:" + domainType.getSimpleName() + ") WHERE n.name CONTAINS $name RETURN COUNT(n)";
Long total = neo4jOperations.count(countQuery, parameters);
return new PageImpl(results, pageable, total);
}
}
@SpringBootApplication
@EnableNeo4jAuditing
@EnableNeo4jCustomRepository
public class NeoApp {
public static void main(String[] args) {
SpringApplication.run(NeoApp.class, args);
}
}
参与评论
手机查看
返回顶部