Spring Data JPA的自动配置类,在一定的条件下开启
1.JpaRepositoriesAutoConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(DataSource.class) //判断是否配置了数据源
@ConditionalOnClass(JpaRepository.class) //判断是否配置了JpaRepository
@ConditionalOnMissingBean({ JpaRepositoryFactoryBean.class, JpaRepositoryConfigExtension.class })
@ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "enabled", havingValue = "true",
matchIfMissing = true) //判断是否在application.properties里是否开启了此enabled
@import(JpaRepositoriesRegistrar.class) //持久层注册器
@AutoConfigureAfter({ HibernateJpaAutoConfiguration.class, TaskExecutionAutoConfiguration.class })
public class JpaRepositoriesAutoConfiguration {
//-------------------------省略里面的启动代码,(其实是看不懂,先不管)
}
Spring Data Jpa提供的各种Repository接口
| Repository |
|---|
| CrudRepository |
| PagingAndSortingRepository |
| JpaRepository |
| 以上四种Repository接口是依次继承的,并在JpaRepository接口中最完善 |
Repository源码,Repository是这四个Repository中作为基类的接口,需要提供T,ID两个泛型
@Indexed public interface Repository{ }
使用方法:在持久层接口中继承此接口即可。
在持久层接口中再按一定的规则编写接口方法即可,
Spring启动扫描后会自动为你定义的方法生成实现类(前提是方法命名正确,且使用@Repository注解)
在此不详细介绍方法命名规则,
我直接给出官方文档的方法命名规则的链接
Spring Data JPA - Reference documentation
另外也有很多人做出了分享,可以Repository方法命名规则即可
CrudRepository顾名思义:增删改查Repository,在其中为我们定义了一些我们要用到的基础的增删改查方法
源码:
@NoRepositoryBean public interface CrudRepositoryextends Repository { //保存一个实体Entity对象,(可以是该对象的子类,因为有可能是继承映射的关系) S save(S entity); //通过泛型的迭代器来保存一个集合类型的实体 例 :saveAll(new ArrayList().iterator())IterablesaveAll(Iterableentities); //很简单,通过ID查询 OptionalfindById(ID id); //通过ID判断 boolean existsById(ID id); //查找所有实体类 Iterable findAll(); //寻找指定ID集合的对象 Iterable findAllById(Iterable ids); //计算实体个数,(很简单,只需要一个简单的聚合函数就可以办到) long count(); //通过指定ID删除 void deleteById(ID id); //传入实体对象进行删除 void delete(T entity); //根据传入的ID集合进行删除 void deleteAllById(Iterable extends ID> ids); void deleteAll(Iterable extends T> entities); void deleteAll(); }
为我们定义了一些通用的持久层方法,很实用
PagingAndSortingRepository分页和排序repository,在CRUDrepository的基础上进一步提供了分页和排序的功能
前言:
JPA的排序源于Hibernate的排序,
可以在hibernate的mapping的集合属性中设置order-by关键字
也有@OrderBy注解可以进行排序
在典型的Hibernate的Query查询中
Query对象有.setFristResult(int arg0)和setMaxResult方法,
Query query = entityManager.createQuery("from article").setFirstResult(arg0);
query.setMaxResults(arg0)
//FirstResult无疑是开始编号
//MaxResults无疑是返回结果的数量(页的记录数)
//通过这两个方法就可以完成数据库的分页操作,(sql语句的数据库分页,不同于mybatis的内存分页,个人认为此方面Hibernate更加优秀)
源码:
@NoRepositoryBean public interface PagingAndSortingRepositoryextends CrudRepository { //传入一个实现sort实例进行全部查找,(sort是一个类) Iterable findAll(Sort sort); //通过实现了pageable接口的对象进行查找 Page findAll(Pageable pageable); }
官方文档链接,(这里官网的示例展示的比较简单,需要自行查看,pageable源码)
Spring Data JPA - Reference documentation
Sort工具类(来自springData的domain包)Sort对象是一个典型的工具类,用于描述JPA(同样可用于SpringData的其他框架)的排序规则
使用方法:不需要自定义类去继承Sort,Sort类自带静态方法可以指定排序规则
Sort源码:
public class Sort implements Streamable, Serializable { private static final long serialVersionUID = 5737186511678863905L; private static final Sort UNSORTED = Sort.by(new Order[0]); //静态常量unsorted代表未排序 public static final Direction DEFAULT_DIRECTION = Direction.ASC; //默认排序方向ASC顺序,可改为DESC逆序 //静态内部类Order集合 private final List orders; protected Sort(List orders) { this.orders = orders; } //私有构造函数,通过Direction对象和属性集合排序 private Sort(Direction direction, List properties) { if (properties == null || properties.isEmpty()) { throw new IllegalArgumentException("You have to provide at least one property to sort by!"); } //这个操作使用了流操作,将String的集合转化为Order集合,很妙! this.orders = properties.stream() // .map(it -> new Order(direction, it)) // .collect(Collectors.toList()); } //通过Entity的属性进行排序,返回一个Sort对象 public static Sort by(String... properties) { Assert.notNull(properties, "Properties must not be null!"); return properties.length == 0 // ? Sort.unsorted() // : new Sort(DEFAULT_DIRECTION, Arrays.asList(properties)); } //根据Order集合进行排序,这里的Order是Sort类的静态内部类,下面有其定义 public static Sort by(List orders) { Assert.notNull(orders, "Orders must not be null!"); return orders.isEmpty() ? Sort.unsorted() : new Sort(orders); } public static Sort by(Order... orders) { Assert.notNull(orders, "Orders must not be null!"); return new Sort(Arrays.asList(orders)); } public static Sort by(Direction direction, String... properties) { Assert.notNull(direction, "Direction must not be null!"); Assert.notNull(properties, "Properties must not be null!"); Assert.isTrue(properties.length > 0, "At least one property must be given!"); return Sort.by(Arrays.stream(properties)// .map(it -> new Order(direction, it))// .collect(Collectors.toList())); } public static TypedSort sort(Class type) { return new TypedSort<>(type); } //静态方法,返回不排序的常量 public static Sort unsorted() { return UNSORTED; } //排序接口呈倒叙 public Sort descending() { return withDirection(Direction.DESC); } //排序接口呈先序 public Sort ascending() { return withDirection(Direction.ASC); } public boolean isSorted() { return !isEmpty(); } @Override public boolean isEmpty() { return orders.isEmpty(); } public boolean isUnsorted() { return !isSorted(); } //排序条件的叠加 public Sort and(Sort sort) { Assert.notNull(sort, "Sort must not be null!"); ArrayList these = new ArrayList<>(this.toList()); for (Order order : sort) { these.add(order); } return Sort.by(these); } //获取属性的Order @Nullable public Order getOrderFor(String property) { for (Order order : this) { if (order.getProperty().equals(property)) { return order; } } return null; } //获取Order集合的迭代器 public Iterator iterator() { return this.orders.iterator(); } //重写了equals方法 @Override public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } if (!(obj instanceof Sort)) { return false; } Sort that = (Sort) obj; return toList().equals(that.toList()); } //重写了hashCode方法 @Override public int hashCode() { int result = 17; result = 31 * result + orders.hashCode(); return result; } //重写了toString @Override public String toString() { return isEmpty() ? "UNSORTED" : StringUtils.collectionToCommaDelimitedString(orders); } //私有方法,在前面的方法中被调用 private Sort withDirection(Direction direction) { return Sort.by(stream().map(it -> new Order(direction, it.getProperty())).collect(Collectors.toList())); } public static enum Direction { ASC, DESC; //是否为升序 public boolean isAscending() { return this.equals(ASC); } //是否为倒叙 public boolean isDescending() { return this.equals(DESC); } //将字符串转化为ASC或者DESC,否则跑个非法参数异常 public static Direction fromString(String value) { try { return Direction.valueOf(value.toUpperCase(Locale.US)); } catch (Exception e) { throw new IllegalArgumentException(String.format( "Invalid value '%s' for orders given! Has to be either 'desc' or 'asc' (case insensitive).", value), e); } } public static Optional fromOptionalString(String value) { try { return Optional.of(fromString(value)); } catch (IllegalArgumentException e) { return Optional.empty(); } } } public static enum NullHandling { NATIVE, NULLS_FIRST, NULLS_LAST; } //内部类Order public static class Order implements Serializable { private static final long serialVersionUID = 1522511010900108987L; private static final boolean DEFAULT_IGNORE_CASE = false; private static final NullHandling DEFAULT_NULL_HANDLING = NullHandling.NATIVE; private final Direction direction; //排序方式 private final String property; //Entity属性名 private final boolean ignoreCase; //是否忽略大小写 private final NullHandling nullHandling; //nullhandling对象 public Order(@Nullable Direction direction, String property) { this(direction, property, DEFAULT_IGNORE_CASE, DEFAULT_NULL_HANDLING); } public Order(@Nullable Direction direction, String property, NullHandling nullHandlingHint) { this(direction, property, DEFAULT_IGNORE_CASE, nullHandlingHint); } public static Order by(String property) { return new Order(DEFAULT_DIRECTION, property); } public static Order asc(String property) { return new Order(Direction.ASC, property, DEFAULT_NULL_HANDLING); } public static Order desc(String property) { return new Order(Direction.DESC, property, DEFAULT_NULL_HANDLING); } private Order(@Nullable Direction direction, String property, boolean ignoreCase, NullHandling nullHandling) { if (!StringUtils.hasText(property)) { throw new IllegalArgumentException("Property must not null or empty!"); } this.direction = direction == null ? DEFAULT_DIRECTION : direction; this.property = property; this.ignoreCase = ignoreCase; this.nullHandling = nullHandling; } public Direction getDirection() { return direction; } public String getProperty() { return property; } public boolean isAscending() { return this.direction.isAscending(); } public boolean isDescending() { return this.direction.isDescending(); } public boolean isIgnoreCase() { return ignoreCase; } public Order with(Direction direction) { return new Order(direction, this.property, this.ignoreCase, this.nullHandling); } public Order withProperty(String property) { return new Order(this.direction, property, this.ignoreCase, this.nullHandling); } public Sort withProperties(String... properties) { return Sort.by(this.direction, properties); } public Order ignoreCase() { return new Order(direction, property, true, nullHandling); } public Order with(NullHandling nullHandling) { return new Order(direction, this.property, ignoreCase, nullHandling); } public Order nullsFirst() { return with(NullHandling.NULLS_FIRST); } public Order nullsLast() { return with(NullHandling.NULLS_LAST); } public Order nullsNative() { return with(NullHandling.NATIVE); } public NullHandling getNullHandling() { return nullHandling; } @Override public int hashCode() { int result = 17; result = 31 * result + direction.hashCode(); result = 31 * result + property.hashCode(); result = 31 * result + (ignoreCase ? 1 : 0); result = 31 * result + nullHandling.hashCode(); return result; } @Override public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } if (!(obj instanceof Order)) { return false; } Order that = (Order) obj; return this.direction.equals(that.direction) && this.property.equals(that.property) && this.ignoreCase == that.ignoreCase && this.nullHandling.equals(that.nullHandling); } @Override public String toString() { String result = String.format("%s: %s", property, direction); if (!NullHandling.NATIVE.equals(nullHandling)) { result += ", " + nullHandling; } if (ignoreCase) { result += ", ignoring case"; } return result; } } //官网上说是新特性,为类型安全的Sort //https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.paging-and-sorting public static class TypedSort extends Sort { private static final long serialVersionUID = -3550403511206745880L; private final Recorded recorded; private TypedSort(Class type) { this(MethodInvocationRecorder.forProxyOf(type)); } private TypedSort(Recorded recorded) { super(Collections.emptyList()); this.recorded = recorded; } public TypedSortby(Functionproperty) { return new TypedSort<>(recorded.record(property)); } public TypedSortby(Recorded.ToCollectionConvertercollectionProperty) { return new TypedSort<>(recorded.record(collectionProperty)); } public TypedSortby(Recorded.ToMapConvertermapProperty) { return new TypedSort<>(recorded.record(mapProperty)); } @Override public Sort ascending() { return withDirection(Sort::ascending); } @Override public Sort descending() { return withDirection(Sort::descending); } private Sort withDirection(Function direction) { return recorded.getPropertyPath() // .map(Sort::by) // .map(direction) // .orElseGet(Sort::unsorted); } @Override public Iterator iterator() { return recorded.getPropertyPath() // .map(Order::by) // .map(Collections::singleton) // .orElseGet(Collections::emptySet).iterator(); } @Override public boolean isEmpty() { return !recorded.getPropertyPath().isPresent(); } @Override public String toString() { return recorded.getPropertyPath() // .map(Sort::by) // .orElseGet(Sort::unsorted) // .toString(); } } }
Sort类型的使用
Sort (Spring Data Core 2.5.5 API)
参考文章
(1条消息) Spring data jpa sort多属性排序问题_MOON-CSDN博客
Pageable接口:(来自springData的domain包)
public interface Pageable {
//不分页
static Pageable unpaged() {
return Unpaged.INSTANCE;
}
//静态方法,返回Pageable实例,PageRequest是其实现类
static Pageable ofSize(int pageSize) {
return PageRequest.of(0, pageSize);
}
//是否分页
default boolean isPaged() {
return true;
}
//是否没分页
default boolean isUnpaged() {
return !isPaged();
}
//获取页数
int getPageNumber();
//获取页的内容数量(page的Size)
int getPageSize();
long getOffset();
//获取分页的排序对象
Sort getSort();
//上述方法的默认实现
default Sort getSortOr(Sort sort) {
Assert.notNull(sort, "Fallback Sort must not be null!");
return getSort().isSorted() ? getSort() : sort;
}
//获取下一页的实例
Pageable next();
//前一页或第一页
Pageable previousOrFirst();
//获取第一页
Pageable first();
//获取指定页数的数据
Pageable withPage(int pageNumber);
//是否有前一页
boolean hasPrevious();
default Optional toOptional() {
return isUnpaged() ? Optional.empty() : Optional.of(this);
}
}
实现类PageRequest,
public class PageRequest extends AbstractPageRequest { //他基础的AbstractPageRequest实现类Pageable接口
private static final long serialVersionUID = -4541509938956089562L;
private final Sort sort;
protected PageRequest(int page, int size, Sort sort) {
super(page, size);
Assert.notNull(sort, "Sort must not be null!");
this.sort = sort;
}
//默认不排序的分页,
//静态方法,返回PageRequest实例
public static PageRequest of(int page, int size) {
return of(page, size, Sort.unsorted());
}
//传入Sort对象进行分页
//静态方法,返回PageRequest实例
public static PageRequest of(int page, int size, Sort sort) {
return new PageRequest(page, size, sort);
}
//还是使用Sort类的方法进行排序,只是形参有点区别
public static PageRequest of(int page, int size, Direction direction, String... properties) {
return of(page, size, Sort.by(direction, properties));
}
public static PageRequest ofSize(int pageSize) {
return PageRequest.of(0, pageSize);
}
public Sort getSort() {
return sort;
}
//下面是Pageable接口的具体实现
@Override
public PageRequest next() {
return new PageRequest(getPageNumber() + 1, getPageSize(), getSort());
}
@Override
public PageRequest previous() {
return getPageNumber() == 0 ? this : new PageRequest(getPageNumber() - 1, getPageSize(), getSort());
}
@Override
public PageRequest first() {
return new PageRequest(0, getPageSize(), getSort());
}
@Override
public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof PageRequest)) {
return false;
}
PageRequest that = (PageRequest) obj;
return super.equals(that) && this.sort.equals(that.sort);
}
@Override
public PageRequest withPage(int pageNumber) {
return new PageRequest(pageNumber, getPageSize(), getSort());
}
public PageRequest withSort(Direction direction, String... properties) {
return new PageRequest(getPageNumber(), getPageSize(), Sort.by(direction, properties));
}
public PageRequest withSort(Sort sort) {
return new PageRequest(getPageNumber(), getPageSize(), sort);
}
@Override
public int hashCode() {
return 31 * super.hashCode() + sort.hashCode();
}
@Override
public String toString() {
return String.format("Page request [number: %d, size %d, sort: %s]", getPageNumber(), getPageSize(), sort);
}
}
然后再看一眼AbstractPageRequest
public abstract class AbstractPageRequest implements Pageable, Serializable {
private static final long serialVersionUID = 1232825578694716871L;
private final int page;
private final int size;
public AbstractPageRequest(int page, int size) {
if (page < 0) {
throw new IllegalArgumentException("Page index must not be less than zero!");
}
if (size < 1) {
throw new IllegalArgumentException("Page size must not be less than one!");
}
this.page = page;
this.size = size;
}
public int getPageSize() {
return size;
}
public int getPageNumber() {
return page;
}
public long getOffset() {
return (long) page * (long) size;
}
public boolean hasPrevious() {
return page > 0;
}
public Pageable previousOrFirst() {
return hasPrevious() ? previous() : first();
}
public abstract Pageable next();
public abstract Pageable previous();
public abstract Pageable first();
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + page;
result = prime * result + size;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
AbstractPageRequest other = (AbstractPageRequest) obj;
return this.page == other.page && this.size == other.size;
}
}
JpaRepository@NoRepositoryBean public interface JpaRepositoryextends PagingAndSortingRepository , QueryByExampleExecutor { //继承了P&S Repository,还有Example查询接口 @Override List findAll(); @Override List findAll(Sort sort); @Override List findAllById(Iterable ids); @Override ListsaveAll(Iterableentities); void flush();S saveAndFlush(S entity);ListsaveAllAndFlush(Iterableentities); @Deprecated default void deleteInBatch(Iterableentities){deleteAllInBatch(entities);} void deleteAllInBatch(Iterable entities); void deleteAllByIdInBatch(Iterable ids); void deleteAllInBatch(); @Deprecated T getOne(ID id); T getById(ID id); @Override ListfindAll(Exampleexample); @OverrideListfindAll(Exampleexample, Sort sort); }
一路继承到JpaRepository已经有很多方法提供了,在它的基础上还继承了Example查询的接口QueryByExampleExecutor
public interface QueryByExampleExecutor{ OptionalfindOne(Exampleexample);IterablefindAll(Exampleexample);IterablefindAll(Exampleexample, Sort sort);PagefindAll(Exampleexample, Pageable pageable);long count(Exampleexample);boolean exists(Exampleexample); }
(Example查询很像Hibernate提供的QBC查询(QueryByCritria),QBC提供一个Critria表示条件,可以通过Restriction的静态方法获取实例)
而Example则要通过构造泛型对象进行查询,
个人感觉:既然在Hibernate中就不是很推荐使用QBC,那这个Example查询我也不是很推荐,能用HQL或JPQL表达清楚的查询为什 么要包装成对象?
SpringDataJpa提供的Repository实现类SimpleJpaRepository在扫描了我们自定义的Repository接口后,Spring会根据我们的配置信息创建SimpleJpaRepository
@Repository @Transactional(readonly = true) public class SimpleJpaRepositoryRepositoryFactory持久层工厂implements JpaRepositoryImplementation { //该接口继承了JpaRepository接口 private static final String ID_MUST_NOT_BE_NULL = "The given id must not be null!"; private final JpaEntityInformation entityInformation; //实体类信息 private final EntityManager em; //重要:Session,过去的Hibernate原生用法,我们要使用session来完成大多数的操作,现在Spring Data 默认为我们生成这个持久层Repository对象(在JPA里Session叫EntityManage.SessionFactory叫EntityManageFactory) private final PersistenceProvider provider; private @Nullable CrudMethodmetadata metadata; //增删改查方法信息 private EscapeCharacter escapeCharacter = EscapeCharacter.DEFAULT; //字符逃逸,转译掉特殊字符,防止SQL注入 //构造方法 public SimpleJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager) { Assert.notNull(entityInformation, "JpaEntityInformation must not be null!"); Assert.notNull(entityManager, "EntityManager must not be null!"); this.entityInformation = entityInformation; this.em = entityManager; this.provider = PersistenceProvider.fromEntityManager(entityManager); } //构造方法重载 public SimpleJpaRepository(Class domainClass, EntityManager em) { this(JpaEntityInformationSupport.getEntityInformation(domainClass, em), em); } //。。。。。。。。。。。。。。。。。。。。。。。。。。此处省略1000行,下面大多是一些方法实现 }
持久层工厂,顾名思义,即以工厂模式生产Repository对象即上述的SimpleJpaRepository
看看JpaRepositoryFactoryBean
public class JpaRepositoryFactoryBean, S, ID> extends TransactionalRepositoryFactoryBeanSupport { private @Nullable EntityManager entityManager; private EntityPathResolver entityPathResolver; private EscapeCharacter escapeCharacter = EscapeCharacter.DEFAULT; private JpaQueryMethodFactory queryMethodFactory; public JpaRepositoryFactoryBean(Class extends T> repositoryInterface) { super(repositoryInterface); } //JPA的注解,从IOC容器的EntityManageFactory里获取EntityManage(Session) @PersistenceContext public void setEntityManager(EntityManager entityManager) { this.entityManager = entityManager; } //获取实体类注解生产的mapping内容 @Override public void setMappingContext(MappingContext, ?> mappingContext) { super.setMappingContext(mappingContext); } //注入实体类的路径 @Autowired public void setEntityPathResolver(ObjectProvider resolver) { this.entityPathResolver = resolver.getIfAvailable(() -> SimpleEntityPathResolver.INSTANCE); } //注入查询方法工厂 @Autowired public void setQueryMethodFactory(@Nullable JpaQueryMethodFactory factory) { if (factory != null) { this.queryMethodFactory = factory; } } //创建RepositoryFactory @Override protected RepositoryFactorySupport doCreateRepositoryFactory() { Assert.state(entityManager != null, "EntityManager must not be null!"); return createRepositoryFactory(entityManager); } protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { JpaRepositoryFactory jpaRepositoryFactory = new JpaRepositoryFactory(entityManager); jpaRepositoryFactory.setEntityPathResolver(entityPathResolver); jpaRepositoryFactory.setEscapeCharacter(escapeCharacter); if (queryMethodFactory != null) { jpaRepositoryFactory.setQueryMethodFactory(queryMethodFactory); } return jpaRepositoryFactory; } @Override public void afterPropertiesSet() { Assert.state(entityManager != null, "EntityManager must not be null!"); super.afterPropertiesSet(); } public void setEscapeCharacter(char escapeCharacter) { this.escapeCharacter = EscapeCharacter.of(escapeCharacter); } }
public class JpaRepositoryFactory extends RepositoryFactorySupport {
private final EntityManager entityManager;
private final QueryExtractor extractor;
private final CrudMethodmetadataPostProcessor crudMethodmetadataPostProcessor;
private EntityPathResolver entityPathResolver;
private EscapeCharacter escapeCharacter = EscapeCharacter.DEFAULT;
private JpaQueryMethodFactory queryMethodFactory;
public JpaRepositoryFactory(EntityManager entityManager) {
Assert.notNull(entityManager, "EntityManager must not be null!");
this.entityManager = entityManager;
this.extractor = PersistenceProvider.fromEntityManager(entityManager);
this.crudMethodmetadataPostProcessor = new CrudMethodmetadataPostProcessor();
this.entityPathResolver = SimpleEntityPathResolver.INSTANCE;
this.queryMethodFactory = new DefaultJpaQueryMethodFactory(extractor);
addRepositoryProxyPostProcessor(crudMethodmetadataPostProcessor);
addRepositoryProxyPostProcessor((factory, repositoryInformation) -> {
if (hasMethodReturningStream(repositoryInformation.getRepositoryInterface())) {
factory.addAdvice(SurroundingTransactionDetectorMethodInterceptor.INSTANCE);
}
});
if (extractor.equals(PersistenceProvider.ECLIPSElink)) {
addQueryCreationListener(new EclipselinkProjectionQueryCreationListener(entityManager));
}
}
@Override
protected final JpaRepositoryImplementation, ?> getTargetRepository(RepositoryInformation information) {
JpaRepositoryImplementation, ?> repository = getTargetRepository(information, entityManager);
repository.setRepositoryMethodmetadata(crudMethodmetadataPostProcessor.getCrudMethodmetadata());
repository.setEscapeCharacter(escapeCharacter);
return repository;
}
//返回一个实现JpaRepositoryImplementation, ?>接口的实例,肯定是SimpleJpaRepository
protected JpaRepositoryImplementation, ?> getTargetRepository(RepositoryInformation information,
EntityManager entityManager) {
JpaEntityInformation, Serializable> entityInformation = getEntityInformation(information.getDomainType());
Object repository = getTargetRepositoryViaReflection(information, entityInformation, entityManager);
Assert.isInstanceOf(JpaRepositoryImplementation.class, repository);
return (JpaRepositoryImplementation, ?>) repository;
}
//直接返回了一个SimpleJpaRepository类
@Override
protected Class> getRepositorybaseClass(Repositorymetadata metadata) {
return SimpleJpaRepository.class;
}
@Override
@SuppressWarnings("unchecked")
public JpaEntityInformation getEntityInformation(Class domainClass) {
return (JpaEntityInformation) JpaEntityInformationSupport.getEntityInformation(domainClass, entityManager);
}
//------------------------省略了一些看不懂的----------------------
}
最后看一下类图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uyxt5bBF-1633519359935)(F:LocalTyproPictruedatajpa.png)]
y = getTargetRepository(information, entityManager);
repository.setRepositoryMethodmetadata(crudMethodmetadataPostProcessor.getCrudMethodmetadata());
repository.setEscapeCharacter(escapeCharacter);
return repository;
}
//返回一个实现JpaRepositoryImplementation, ?>接口的实例,肯定是SimpleJpaRepository
protected JpaRepositoryImplementation, ?> getTargetRepository(RepositoryInformation information,
EntityManager entityManager) {
JpaEntityInformation, Serializable> entityInformation = getEntityInformation(information.getDomainType());
Object repository = getTargetRepositoryViaReflection(information, entityInformation, entityManager);
Assert.isInstanceOf(JpaRepositoryImplementation.class, repository);
return (JpaRepositoryImplementation, ?>) repository;
}
//直接返回了一个SimpleJpaRepository类
@Override
protected Class> getRepositorybaseClass(Repositorymetadata metadata) {
return SimpleJpaRepository.class;
}
@Override
@SuppressWarnings("unchecked")
public JpaEntityInformation getEntityInformation(Class domainClass) {
return (JpaEntityInformation) JpaEntityInformationSupport.getEntityInformation(domainClass, entityManager);
}
//------------------------省略了一些看不懂的----------------------
}
最后看一下类图
感想:源码里大量的使用了流操作和Optional操作,很有学习价值



