惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog RSS Feed
C
CERT Recently Published Vulnerability Notes
P
Proofpoint News Feed
Y
Y Combinator Blog
T
The Blog of Author Tim Ferriss
云风的 BLOG
云风的 BLOG
H
Help Net Security
Recorded Future
Recorded Future
The Register - Security
The Register - Security
F
Full Disclosure
N
Netflix TechBlog - Medium
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hackread – Cybersecurity News, Data Breaches, AI and More
爱范儿
爱范儿
Security Archives - TechRepublic
Security Archives - TechRepublic
Simon Willison's Weblog
Simon Willison's Weblog
Cisco Talos Blog
Cisco Talos Blog
I
InfoQ
T
Tenable Blog
T
Tor Project blog
人人都是产品经理
人人都是产品经理
D
DataBreaches.Net
NISL@THU
NISL@THU
Google DeepMind News
Google DeepMind News
博客园 - 叶小钗
B
Blog
V
V2EX
Jina AI
Jina AI
L
LangChain Blog
月光博客
月光博客
W
WeLiveSecurity
U
Unit 42
AWS News Blog
AWS News Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
博客园 - 聂微东
V
Visual Studio Blog
A
Arctic Wolf
T
Tailwind CSS Blog
The Cloudflare Blog
SecWiki News
SecWiki News
S
SegmentFault 最新的问题
Hacker News - Newest:
Hacker News - Newest: "LLM"
宝玉的分享
宝玉的分享
MyScale Blog
MyScale Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
Securelist
www.infosecurity-magazine.com
www.infosecurity-magazine.com
腾讯CDC
雷峰网
雷峰网

Moon's Blog

Java内存 | Moon's Blog Spring Boot的Java Config | Moon's Blog Java知识点 | Moon's Blog Spring Boot知识点 | Moon's Blog Java异常机制 | Moon's Blog Java的类加载器 | Moon's Blog JVM类加载机制 | Moon's Blog 单体架构与微服务架构 | Moon's Blog 424.替换后的最长重复字符 | Moon's Blog 888.公平的糖果棒交换 | Moon's Blog 839.相似字符串组 | Moon's Blog 778.水位上升的泳池中游泳 | Moon's Blog 1631.最小体力消耗路径 | Moon's Blog 724.寻找数组的中心索引 | Moon's Blog 使用Jackson库实现日期序列化 | Moon's Blog 使用Jackson库实现Java多态解析 | Moon's Blog Spring Boot+InfluxDB实现日志管理 | Moon's Blog Java多态+工厂模式实现服务调用 | Moon's Blog 为Spring Boot项目生成OpenAPI3.0文档 | Moon's Blog
Spring Data JPA | Moon's Blog
Moon Lou · 2021-03-14 · via Moon's Blog

Spring Data JPA是基于HibernateJPA规范的一套ORM框架。目前主流的ORM框架有:

  • MyBatis
  • Hibernate
  • Spring Data JPA
  • Spring JDBC Template

1. Spring Data

Spring Data旨在简化对数据库或者数据存储(比如缓存)的持久化操作,且不拘泥于关系型SQL,同时支持NoSQL数据库,比如文档数据库MongoDB、图数据库Neo4j、键/值存储Redis等。

上图是Spring Data的项目架构,包含Spring Data JPASpring Data MongoDBSpring Data Neo4j等子项目,以分别匹配不同类型的数据库。

Repository接口是Spring Data的核心接口,不提供任何方法,是一个空接口,也就是一个标记接口。当我们声明的接口继承该接口时,会自动将我们的接口归入Spring容器管理。

  • Repository<T, ID>
@Indexed
public interface Repository<T, ID> {
}
  • CrudRepository<T, ID> 继承自Repository<T, ID>,封装了简单的增删改查操作
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S var1);

<S extends T> Iterable<S> saveAll(Iterable<S> var1);

Optional<T> findById(ID var1);

boolean existsById(ID var1);

Iterable<T> findAll();

Iterable<T> findAllById(Iterable<ID> var1);

long count();

void deleteById(ID var1);

void delete(T var1);

void deleteAll(Iterable<? extends T> var1);

void deleteAll();
}
  • PagingAndSortingRepository<T, ID> 继承自CrudRepository<T, ID>,实现了分页与排序功能
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort var1);

Page<T> findAll(Pageable var1);
}

2.JPA(Java Persistence API,Java持久化API)

JPA是一个Java持久化接口规范,为Java开发人员提供了一种对象/关系映射(ORM)工具来管理Java应用中的关系数据。但是JPA只是一种接口规范,并不是一套直接可用的产品(比如Hibernate)。

3.Spring Data JPA

Spring Data JPA是Spring Data的一个子项目,是基于Hibernate、JPA规范的基础上封装的一套ORM框架,可以说是JPA规范的一个实践落地的产品。内置实现了包括增删改查、分页、自定义SQL的常用功能,以简洁的代码快速实现关系数据库访问。

JPARepository<T, ID>是Spring Data JPA的核心接口,它继承自PagingAndSortingRepository<T, ID>接口,同时实现了JPA的相关规范:

@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();

List<T> findAll(Sort var1);

List<T> findAllById(Iterable<ID> var1);

<S extends T> List<S> saveAll(Iterable<S> var1);


void flush();

<S extends T> S saveAndFlush(S var1);

void deleteInBatch(Iterable<T> var1);

void deleteAllInBatch();

T getOne(ID var1);

<S extends T> List<S> findAll(Example<S> var1);

<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}

在使用Spring Data JPA时,只需要继承JPARepository接口,在声明方法时按照特定规则进行声明,Spring框架底层会自动帮我们实现这些方法,从而实现快速的增删改查、分页排序功能。

但是对于一些复杂查询(比如对两张数据表的级联查询),很难通过方法名来构造,这时需要@Query注解,通过自定义SQL来实现复杂查询:

@Query("select user from User u where u.userName=?1 and u.age=?2 ")
User getUserByUserNameAndAge2(String userName,Integer age);

当需要更新和删除操作,加一个@Modifying注解:

@Modifying
@Query("UPDATE User u set u.userName =: userName where u.age =:age")
void update(@Param(value = "userName") String userName, @Param(value = "age")Integer age);

4.Spring Data MongoDB

Spring Data MongoDBSpring Data JPA同级,都是Spring Data的子项目,其核心是MongoRepository+MongoTemplate。它的核心接口MongoRepository<T, ID>也是继承自PagingAndSortingRepository<T, ID>接口:

@NoRepositoryBean
public interface MongoRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
<S extends T> List<S> saveAll(Iterable<S> var1);

List<T> findAll();

List<T> findAll(Sort var1);

<S extends T> S insert(S var1);

<S extends T> List<S> insert(Iterable<S> var1);

<S extends T> List<S> findAll(Example<S> var1);

<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}

与JPARepository同理,通过继承MongoRepository,并按规则声明方法,Spring底层会自动实现方法,从而快速地对MongoDB进行增删改查、分页排序等操作:

@Repository
public interface MetadataRepository extends MongoRepository<Metadata, String>, CustomMetadataRepository {
Boolean existsByIdAndOwnerId(String id, String ownerId);

List<Metadata> findAllByImageId(String imageId);
}

遇到复杂查询问题,与Spring Data JPA不同,Spring Data MongoDB提供了MongoTemplate,支持自定义的复杂查询操作,核心类是Query与Criteria:

@Repository
public class InstanceRepositoryImpl implements CustomInstanceRepository {
@Autowired
MongoTemplate mongoTemplate;

@Override
public Instance queryByIp(String ip) {
Query query = new Query();
query.addCriteria(Criteria.where("ip").is(ip));
Instance instance = mongoTemplate.findOne(query, Instance.class);
if (instance == null) {
throw new ObjectNotFoundException("服务实例");
}
return instance;
}

@Override
public List<Instance> findAllByMetadataId(String metadataId) {
Query query = new Query();
query.addCriteria(Criteria.where("metadataId").is(metadataId));
return mongoTemplate.find(query, Instance.class);
}

@Override
public List<Instance> findAllByImageId(String imageId) {
Query query = new Query();
query.addCriteria(Criteria.where("imageId").is(imageId));
return mongoTemplate.find(query, Instance.class);
}

}

5.MyBatis

Mybatis是一款优秀的持久层框架,他支持自定义SQL、存储过程以及高级映射。Mybatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。Mybatis可以通过简单的XML或注解来配置和映射原始类型、接口和Java POJO(Plain Old Java Objects,普通老式Java对象)为数据库中的记录。

6.Spring Data JPA与MyBatis对比

JPA默认使用Hibernate作为ORM实现,Hibernate是面向对象的,而MyBatis是面向关系的

  • 面向对象考虑的是对象的整个生命周期,包括在对象的创建、持久化、状态的改变和行为等,对象的持久化只是对象的一种状态,而面向关系型数据库的概念则更关注数据的高效存储和读取
  • 面向对象更强调对象状态的封装性,对象封装自己的状态(或数据)不允许外部对象随意修改,只暴露一些合法的行为方法供外部对象调用;而关系型数据库则是开放的,可以供用户随意读取和修改关系,并可以和其他表任意的关联(只要sql正确允许的情况下)。
  • 面向对象试图为动态的世界建模,他要描述的是世界的过程和规律,进而适应发展和变化,面向对象总是在变化中处理各种各样的变化。而关系型模型为静态世界建模,它通过数据快照记录了世界在某一时候的状态,它是静态的。

选型规则:

  • 表关联较多的项目,优先使用MyBatis
  • 持续维护开发、迭代较快的项目建议使用MyBatis,因为一般这种项目需要变化很灵活,对sql的灵活修改要求较高
  • 对于传统项目或者关系模型较为清晰稳定的项目,建议JPA
  • 目前微服务比较火,基于其职责的独立性(可能一个微服务只和一张表打交道),如果模型清晰,可以考虑使用JPA,但如果数据量较大全字段返回数据量大的话可能在性能有影响,需要根据实际情况进行分析