spring-data-jpa自定义repository来实现原生sql

Spring Data JPA中的Repository是接口,是JPA根据方法名帮我们自动生成的。但很多时候,我们需要为Repository提供一些自定义的实现。今天我们看看如何为Repository添加自定义的方法。

自定义Repository接口

首先我们来添加一个自定义的接口:

  • 添加BaseRepository接口
  • BaseRepository继承了JpaRepository,这样可以保证所有Repository都有jpa提供的基本方法。
  • BaseRepository上添加@NoRepositoryBean标注,这样Spring Data Jpa在启动时就不会去实例化BaseRepository这个接口
/**
 * Created by liangkun on 2016/12/7.
 */
@NoRepositoryBean
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T,ID> {

    //sql原生查询
    List<Map<String, Object>> listBySQL(String sql);
}

接下来实现BaseRepository接口,并继承SimpleJpaRepository类,使其拥有Jpa Repository的提供的方法实现。

/**
 * Created by liangkun on 2017/12/7.
 */
public class BaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T,ID> implements BaseRepository<T,ID> {

    private final EntityManager entityManager;

    //父类没有不带参数的构造方法,这里手动构造父类
    public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
        super(domainClass, entityManager);
        this.entityManager = entityManager;
    }



    //通过EntityManager来完成查询
    @Override
    public  List<Map<String, Object>> listBySQL(String sql) {
        return entityManager.createNativeQuery(sql).getResultList();
    }
}

这里着重说下EntityManager

EntityManager是JPA中用于增删改查的接口,它的作用相当于一座桥梁,连接内存中的java对象和数据库的数据存储。也可以根据他进行sql的原生查找。

源码如下:

public interface EntityManager {
    
    <T> T find(Class<T> var1, Object var2);

    Query createNativeQuery(String var1);

    Query createNativeQuery(String var1, Class var2);

    Query createNativeQuery(String var1, String var2);
}

由上可以看出其有具体的原生查询实现接口 createNativeQuery

接下来需要将我们自定义的Repository接口,通过工厂模式添加到Spring的容器中:

创建自定义RepositoryFactoryBean

接下来我们来创建一个自定义的RepositoryFactoryBean来代替默认的RepositoryFactoryBeanRepositoryFactoryBean负责返回一个RepositoryFactory,Spring Data Jpa 将使用RepositoryFactory来创建Repository具体实现。

查看JpaRepositoryFactoryBean的源码,通过createRepositoryFactory返回JpaRepositoryFactory实例:

public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
		extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> {

	private EntityManager entityManager;
	
	public JpaRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
		super(repositoryInterface);
	}
	
	@PersistenceContext
	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

	@Override
	public void setMappingContext(MappingContext<?, ?> mappingContext) {
		super.setMappingContext(mappingContext);
	}

	@Override
	protected RepositoryFactorySupport doCreateRepositoryFactory() {
		return createRepositoryFactory(entityManager);
	}

	protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
		return new JpaRepositoryFactory(entityManager);
	}

	@Override
	public void afterPropertiesSet() {

		Assert.notNull(entityManager, "EntityManager must not be null!");
		super.afterPropertiesSet();
	}
}

终上我们可根据相应的规则进行创建自定义RepositoryFactoryBean

/**
 * Created by liangkun on 2018/07/20.
 */
public class BaseRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> {

    public BaseRepositoryFactoryBean(Class<? extends R> repositoryInterface) {
        super(repositoryInterface);
    }

    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
        return new BaseRepositoryFactory(em);
    }

    //创建一个内部类,该类不用在外部访问
    private static class BaseRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {

        private final EntityManager em;

        public BaseRepositoryFactory(EntityManager em) {
            super(em);
            this.em = em;
        }

        //设置具体的实现类是BaseRepositoryImpl
        @Override
        protected Object getTargetRepository(RepositoryInformation information) {
            return new BaseRepositoryImpl<T, I>((Class<T>) information.getDomainType(), em);
        }

        //设置具体的实现类的class
        @Override
        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return BaseRepositoryImpl.class;
        }
    }
}

自定义完成。

猜你喜欢

转载自blog.csdn.net/liangkun_java/article/details/81135795