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

本文介绍如何在Spring Data JPA中自定义Repository接口及其实现,包括创建BaseRepository接口和BaseRepositoryImpl类,以及如何通过自定义RepositoryFactoryBean集成到Spring容器。

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;
        }
    }
}

自定义完成。

 

 

Repository实现数据权限可以通过以下几个步骤: 1. 定义数据权限规则:根据业务需要,定义数据权限规则,例如根据用户角色、部门等限制用户可以查询的数据范围。 2. 实现数据权限逻辑:在Repository实现数据权限的逻辑,通常是在查询方法中添加数据权限的限制条件。可以通过注解、AOP等方式实现数据权限的逻辑。 3. 获取用户信息:在数据权限逻辑中需要获取当前用户的信息,例如用户角色、部门等。可以通过Session、ThreadLocal等方式实现获取用户信息的功能。 4. 应用数据权限规则:根据用户信息和数据权限规则,动态生成查询条件,并添加到查询方法中,以实现数据权限的限制。 下面是一个简单的示例,演示如何在Repository实现数据权限: ```java @Repository public class UserRepositoryImpl implements UserRepository { @Autowired private JdbcTemplate jdbcTemplate; @Override public List<User> findUsersByRole(Role role) { // 获取当前用户信息 User currentUser = getCurrentUser(); // 根据用户角色和数据权限规则生成查询条件 String sql = "SELECT * FROM users WHERE role = ? AND dept_id IN (SELECT dept_id FROM user_dept WHERE user_id = ?)"; // 执行查询,并返回结果 return jdbcTemplate.query(sql, new Object[]{role, currentUser.getId()}, new UserRowMapper()); } // 获取当前用户信息 private User getCurrentUser() { // 从Session或ThreadLocal中获取当前用户信息 // ... } } ``` 在上面的示例中,通过获取当前用户信息和数据权限规则,动态生成了查询条件,并添加到SQL语句中,以实现数据权限的限制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值