blinkfox / fenix

This is an extension library to the Spring Data JPA complex or dynamic SQL query. 这是一个比 MyBatis 更加强大的 Spring Data JPA 扩展库,为解决复杂动态 JPQL (或 SQL) 而生。https://blinkfox.github.io/fenix
https://blinkfox.github.io/fenix
Apache License 2.0
345 stars 72 forks source link

扩展点建议 #5

Closed hexian closed 4 years ago

hexian commented 4 years ago

您好,阅读了您的代码和官方的文档,

官方文档给出的建议是: Spring Data JPA 的版本须保证 2.1.8.RELEASE 及以上;如果你是 Spring Boot 项目,则 Spring Boot 的版本须保证 2.1.5.RELEASE 及以上。因为后续版本的 Spring Data JPA 对其中 QueryLookupStrategy 的代码有较大改动。

在了解到您的项目之前我也做了些相似的工作,通过新的@NativeSelect注解来完成一些对原生sql的增强,且最近正在读mybatis源码,想把mybatis的xml配置能力移植过来,但是半途而废了,不过我这边选择的扩展点是在两个地方:

org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.createRepositoryFactory(EntityManager)

org.springframework.data.repository.core.support.RepositoryFactorySupport.addRepositoryProxyPostProcessor(RepositoryProxyPostProcessor)

通过扩展一个 RepositoryProxyPostProcessor 类来新增切面, 我的一个实现如下:

import javax.persistence.EntityManager;

import org.springframework.aop.framework.ProxyFactory; import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.support.RepositoryProxyPostProcessor;

import com.ducha.repositories.dao.factory.BaseRepositoryFactoryBean.CommonRepositoryFactory; import com.ducha.repositories.dao.interceptor.JpqlSqlMethodInterceptor; import com.ducha.repositories.dao.interceptor.NativeSqlMethodInterceptor; import com.ducha.repositories.dao.interceptor.ResultTransformerMethodInterceptor; import com.ducha.repositories.dao.interceptor.TransformMethodInterceptor; /**

}

public class ResultTransformerMethodInterceptor implements MethodInterceptor {

    @Override
public Object invoke(MethodInvocation invocation) throws Throwable {
            Method method = invocation.getMethod();
            ResultTransformer resultTransformer  = AnnotatedElementUtils.findMergedAnnotation(method, ResultTransformer.class);

    // 判断方法是否是在接口上声明
    boolean isInterface                  = method.getDeclaringClass().isInterface();
    // 同时包含 @ResultTransformer 和 @Query 注解, 且不包含 @Modifying 注解
    if(isInterface && resultTransformer != null) {

        //  ** TODO: 在这里进行对您提供的功能进行集成(动态解析sql) **

        return result;
    } else {
                    // 调用Spring Data JPA原先的切面链
        Object result = invocation.proceed();
        return result;
    }
    }

}

这样的话应该在Spring Boot 1.x 以上都可以支持了(公司老项目使用的是1.x的版本), 我的扩展工作是在: Spring Boot 2.0.2.RELEASE, spring-data-jpa-2.0.7.RELEASE, 这样就可以在较低的版本中使用,我特意在Spring Data JPA的github上看了下,这个扩展点在 spring-data-commons 1.5.x 版本就开始支持了。 您可以看 这里 , 搜索字符串: " postProcess( "

blinkfox commented 4 years ago

可以,后续有时间看看

hexian commented 4 years ago

嗯嗯