@NoRepositoryBean:Spring Data Jpa在启动时就不会去实例化BaseRepository
这个接口
1.通用接口:
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.NoRepositoryBean; /** * 通用DAO接口 * */ @NoRepositoryBean public interface DAOInterface<T> extends JpaRepository<T, Long>, JpaSpecificationExecutor<T> { }
2.添加自定义方法:
2.1自定义Repository接口
@NoRepositoryBean public interface BaseRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> { boolean support(String modelType); }
- 添加
BaseRepository
接口 BaseRepository
继承了PagingAndSortingRepository
,这样可以保证所有Repository都有基本的增删改查以及分页等方法。- 在
BaseRepository
上添加@NoRepositoryBean
标注,这样Spring Data Jpa在启动时就不会去实例化BaseRepository
这个接口 - 添加
support(String modelType)
方法,表示该Repository的领域对象是否为modelType
类型
2.2实现BaseRepository接口
public class BaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> { private final Class<T> domainClass; public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityManager) { super(domainClass, entityManager); this.domainClass = domainClass; } @Override public boolean support(String modelType) { return domainClass.getName().equals(modelType); } }
定义好自定义的方法后,我们现在通过一个基本的Repository类来实现该方法:
首先添加BaseRepositoryImpl类,继承SimpleJpaRepository类,使其拥有Jpa Repository的基本方法。
我们发现Repository有两个构造函数:
- SimpleJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager)
- SimpleJpaRepository(Class domainClass, EntityManager em)
这里我们实现第二个构造函数,拿到domainClass
和EntityManager
两个对象。因为我们要实现的是知道某个Repository是否支持某个领域对象的类型,因此在实现构造函数时我们将domainClass
的信息保留下来。
最后实现support
方法,其参数是领域对象的类型,将其和domainClass
对比,如果相等,则该Repository支持该类型的领域对象:
2.3创建自定义RepositoryFactoryBean
接下来我们来创建一个自定义的RepositoryFactoryBean
来代替默认的RepositoryFactoryBean
。RepositoryFactoryBean
负责返回一个RepositoryFactory
,Spring Data Jpa 将使用RepositoryFactory
来创建Repository具体实现,这里我们用BaseRepositoryImpl
代替SimpleJpaRepository
作为Repository接口的实现。这样我们就能够达到为所有Repository添加自定义方法的目的。
public class BaseRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> { @Override protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) { return new MyRepositoryFactory(em); } private static class MyRepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory { private final EntityManager em; public MyRepositoryFactory(EntityManager em) { super(em); this.em = em; } @Override protected Object getTargetRepository(RepositoryMetadata metadata) { return new BaseRepositoryImpl<T, I>((Class<T>) metadata.getDomainType(), em); } @Override protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { return BaseRepositoryImpl.class; } } }
2.4配置Jpa factory class
最后,我们需要配置Jpa使用我们自定义的BaseRepositoryFactoryBean
。Spring支持使用标注进行配置,我们在com.tmy.App
中添加标注@EnableJpaRepositories(repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class)
:
@SpringBootApplication @EnableJpaRepositories(repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class) public class App { public static void main( String[] args ){ SpringApplication.run(App.class, args); } }
这样我们就为所有Repository添加了自定义的方法。
2.5测试
我们添加了一个TestController
进行测试。进入根目录,执行mvn spring-boot:run
可以运行我们的应用。
应用启动后,分别访问http://localhost:8080/test?type=blog&id=1
和http://localhost:8080/test?type=article&id=1
,我们将看到article和blog两个不同的对象。
在TestController
中,我们通过依赖式注入获取到所有Repository的列表。当用户访问/test
,系统将根据传进来的type
遍历所有Repository,找到对应的Repository,再调用findOne(id)
方法找到对应的对象。这样我们就不需要一个一个的去获取Repository实例,当领域对象越来越多时,通过这种方式是一种更加高效的对象管理方法。
@RestController public class TestController { @Autowired private List<BaseRepository> repositories; @RequestMapping(value = "/test", method=RequestMethod.GET) public Object getEntry(@RequestParam(value="type", required = true) String type, @RequestParam(value="id", required=true) Integer id){ if(type.equals("article")){ type = Article.class.getName(); }else if (type.equals("blog")) { type = Blog.class.getName(); } for (BaseRepository baseRepository : repositories) { if(baseRepository.support(type)){ return baseRepository.findOne(id); } } return null; } }
参考:
https://www.tianmaying.com/tutorial/spring-jpa-custom-all
原文地址:https://www.cnblogs.com/soul-wonder/p/9051649.html