作者 | 阿文

责编 | 屠敏

什么是 JPA

大家好,今天我和大家聊一下关于Spring JPA 的相关知识,我们先来了解下什么是 JPA ?

JPA (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范。它为 Java 开发人员提供了一种对象/关联映射工具来管理 Java 应用中的关系数据。他的出现主要是为了简化现有的持久化开发工作和整合 ORM 技术,结束现在 Hibernate,TopLink,JDO 等 ORM 框架各自为营的凌乱局面。JPA 在充分吸收了现有 Hibernate,TopLink,JDO 等ORM框架的基础上发展而来的,具有易于使用,伸缩性强等优点。从上面的解释中我们可以了解到JPA 是一套规范,而类似 Hibernate,TopLink,JDO 这些产品是实现了 JPA 规范。

了解了什么是 JPA,我们来看看本文的主角——spring data jpa。

spring data jpa

Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套 JPA 应用框架,底层使用了 Hibernate 的 JPA 技术实现,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率。

什么意思呢?如果用过Hibernate或者MyBatis的话,就会知道对象关系映射(ORM)框架有多么方便。但是Spring Data JPA框架功能更进一步,为我们做了 一个数据持久层框架几乎能做的任何事情。以Springboot整合MyBatis为例,比如我们要向数据库中插入一些用户的数据,那么我们需要先定义用户的实体类,然后我们要定义一个UserDao:

@Repository
public class UserDao {@AutowiredJdbcTemplate jdbcTemplate;public int addUser(User user){return jdbcTemplate.update("INSERT INTO t_user(username,jobs,phone) VALUE (?,?,?)",user.getName(),user.getJobs(),user.getPhone());}public int updateUser(User user){return jdbcTemplate.update("UPDATE t_user SET username=?,jobs=?,phone=? WHERE id=?",user.getName(),user.getJobs(),user.getPhone(),user.getId());}public int deleteUser(Integer id){return jdbcTemplate.update("DELETE  FROM t_user WHERE id=?",id);}public User getUserById(Integer id){return jdbcTemplate.queryForObject("SELECT * FROM t_user WHERE id =?",new BeanPropertyRowMapper<>(User.class),id);}public List<User> getAllUser(){return jdbcTemplate.query("SELECT * FROM t_user",new BeanPropertyRowMapper<>(User.class));}
}

以及UserService

@Service
public class UserService {@AutowiredUserDao userDao;public int addUser(User user){return userDao.addUser(user);}public int updateUser(User user){return userDao.updateUser(user);}public int deleteUser(Integer id){return userDao.deleteUser(id);}public  User getUserById(Integer id){return userDao.getUserById(id);}public List<User> getAllUser(){return userDao.getAllUser();}
}

最后,我们在去调用对应的service 中的方法。这是传统的方式,如果使用mapper,会稍微简单一些,比如我们要添加mapper

@Mapper
public interface UserMapper {int addUser(User user);int deleteUser(int id);int updateUser(User user);User getUserById(Integer id);List<User> getAllUsers();}

然后定义一个UserMapper.xml ,添加对应的CURD SQL语句,做好映射,然后改造service,例如

@Service
public class UserService {@AutowiredUserMapper userMapper;public int addUser(User user){return userMapper.addUser(user);}public int updateUser(User user){return userMapper.updateUser(user);}public int deleteUser(Integer id){return userMapper.deleteUser(id);}public  User getUserById(Integer id){return userMapper.getUserById(id);}public List<User> getAllUser(){return userMapper.getAllUsers();}
}

发现什么问题了吗?如果我们要去实现多个表的操作,我们需要定义不同的实体类,然后实现对应的mapper,然后写同样的增删改查方法,最后调用。这也太麻烦了些,而Spring data jpa 则可以轻松的帮我们实现这些繁琐重复且没有技术含量的操作。我们一起看下吧!

案例演示

1.首先,我们需要配置pom.xml

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>

2.然后是application.properties 的配置

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=true

这里重点简单介绍下spring.jpa.properties.hibernate.hbm2ddl.auto有几种配置:

  • create:表示每次加载Hibernate时都会删除上一次生成的表(包括数据),然后重新生成新表,即使两次没有任何修改也会这样执行。适用于每次执行单测前清空数据库的场景。

  • create-drop:表示每次加载Hibernate时都会生成表,但当SessionFactory关闭时,所生成的表将自动删除。

  • update:最常用的属性值,第一次加载Hibernate时创建数据表(前提是需要先有数据库),以后加载Hibernate时不会删除上一次生成的表,会根据实体更新,只新增字段,不会删除字段(即使实体中已经删除)。

  • validate:每次加载Hibernate时都会验证数据表结构,只会和已经存在的数据表进行比较,根据model修改表结构,但不会创建新表。

  • 不配置此项,表示禁用自动建表功能

spring.jpa.show-sql=true 该配置当在执行数据库操作的时候会在控制台打印 sql 语句,方便我们检查排错等。

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect 这是数据库的方言配置。

3.接下来我们建立用户实体类

@Entity
public class User {@Id@GeneratedValueprivate long id;@Column(nullable = false, unique = true)private String userName;@Column(nullable = false)private String password;@Column(nullable = false)private int age;
}

这里的一些注解解释如下:

  • @Entity 是一个类注解,用来注解该类是一个实体类用来进行和数据库中的表建立关联关系,首次启动项目的时候,默认会在数据中生成一个同实体类相同名字的表(table),也可以通过注解中的 name 属性来修改表(table)名称, 如@Entity(name=“user”) , 这样数据库中表的名称则是 user 。该注解十分重要,如果没有该注解首次启动项目的时候你会发现数据库没有生成对应的表。

  • @Table 注解也是一个类注解,该注解可以用来修改表的名字,该注解完全可以忽略掉不用,@Entity 注解已具备该注解的功能。

  • @Id 类的属性注解,该注解表明该属性字段是一个主键,该属性必须具备,不可缺少。

  • @GeneratedValue 该注解通常和 @Id 主键注解一起使用,用来定义主键的呈现形式,该注解通常有多种使用策略,先总结如下:

  • @GeneratedValue(strategy= GenerationType.IDENTITY) 该注解由数据库自动生成,主键自增型,在 mysql 数据库中使用最频繁,oracle 不支持。

  • @GeneratedValue(strategy= GenerationType.AUTO)  主键由程序控制,默认的主键生成策略,oracle 默认是序列化的方式,mysql 默认是主键自增的方式。

  • @GeneratedValue(strategy= GenerationType.SEQUENCE) 根据底层数据库的序列来生成主键,条件是数据库支持序列,Oracle支持,Mysql不支持。

  • @GeneratedValue(strategy= GenerationType.TABLE) 使用一个特定的数据库表格来保存主键,较少使用。

上面这些主键生成策略中,以 mysql 为例,  IDENTITY  和 AUTO 用的较多,二者当中 IDENTITY 用的多些,以下文章当中演示的 demo 主键均使用 @GeneratedValue(strategy= GenerationType.IDENTITY) 的生成策略。

@Column 是一个类的属性注解,该注解可以定义一个字段映射到数据库属性的具体特征,比如字段长度,映射到数据库时属性的具体名字等。

@Transient  是一个属性注解,该注解标注的字段不会被映射到数据库当中。

4. 声明 `UserRepository`接口,继承`JpaRepository`,如下所示

public interface UserRepository extends JpaRepository<User, Long> {}

这里的 JpaRepository继承了接口PagingAndSortingRepository和QueryByExampleExecutor。而,PagingAndSortingRepository又继承CrudRepository。

因此,JpaRepository接口同时拥有了基本CRUD功能以及分页功能。因此,这里我们可以继承JpaRepository,从而获得Spring为我们预先定义的多种基本数据操作方法。

5.然后我们定义一个测试类,  这里我们演示下添加操作, @Transactional 表示开启事务防止出现脏数据。

        ……@Autowiredprivate UserRepository userRepository;@Test@Transactionalpublic void userAddTest() {User user = new User();user.setUserName("吴彦祖");user.setAge(30);user.setPassword("123456");userRepository.save(user);User item = userRepository.findByUserName("wyk");log.info(JsonUtils.toJson(item));}

6.接下来我们说下查询,查询可以分为基本查询和自定义查询,一种是 spring data 默认已经实现,只需要要继承`JpaRepository`,一种是根据查询的方法来自动解析成 SQL。

@Test
public void testQuery() throws Exception {User user=new User();userRepository.findAll();userRepository.findOne(1l);userRepository.save(user);userRepository.delete(user);userRepository.count();userRepository.exists(1l);……
}

7.自定义的简单查询就是根据方法名来自动生成SQL,主要的语法是`findXXBy,readAXXBy,queryXXBy,countXXBy, getXXBy`后面跟属性名称,举几个例子:

User findByUserName(String userName);User findByUserNameOrEmail(String username, String email);Long deleteById(Long id);Long countByUserName(String userName);List<User> findByEmailLike(String email);User findByUserNameIgnoreCase(String userName);List<User> findByUserNameOrderByEmailDesc(String email);

8.接下来,我们说下复杂的查询,在实际的开发中我们需要用到分页、删选、连表等查询的时候就需要特殊的方法或者自定义 SQL,以分页查询为例,分页查询在实际使用中非常普遍了,spring data jpa已经帮我们实现了分页的功能,在查询的方法中,需要传入参数Pageable,当查询中有多个参数的时候Pageable建议做为最后一个参数传入。Pageable是 spring 封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则

Page<User> findALL(Pageable pageable);Page<User> findByUserName(String userName,Pageable pageable);

9.我们看下下面的测试用例

@Test
public void testPageQuery() throws Exception {int page=1,size=5;Sort sort = new Sort(Direction.DESC, "id");Pageable pageable = new PageRequest(page, size, sort);userRepository.findALL(pageable);userRepository.findByUserName("testName", pageable);
}

10. Spring data 大部分的 SQL 都可以根据方法名定义的方式来实现,但是由于某些原因我们想使用自定义的 SQL 来查询,spring data 也是完美支持的,如下所示:

@Modifying
@Query("update User u set u.userName = ?1 where c.id = ?2")
int modifyByIdAndUserId(String  userName, Long id);@Transactional
@Modifying
@Query("delete from User where id = ?1")
void deleteByUserId(Long id);@Transactional(timeout = 10)
@Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);

好啦,以上就是关于spring data jpa 的介绍。

【END】

更多精彩推荐
☞200 个工具分析机器学习十年:前途未卜、工程师是核心!
☞Python 3.9 正式版要来了,会有哪些新特性?
☞零基础编程小白如何拿 Offer?八年经验面试官万字肺腑之言
☞无代码开发到底是不是伪需求?
☞没了Macbook的英特尔还好吗?
☞Spring 从入门到入土——AOP 就这么简单!| 原力计划
☞硬核!国外开发者用 25 美元做了个区块链警佩相机!
你点的每个“在看”,我都认真当成了喜欢

一文搞懂 Spring JPA相关推荐

  1. 一文搞懂Spring,堪称Spring源码终结者

    Spring的影响力想必无需与大家多说,如果你用spring,那么读读源码有助于对你最重要的工具的理解,好的框架源码也可以帮助我们理解什么是好代码. 刚参加工作那会,没想过去读源码,更没想过去改框架的 ...

  2. 一文搞懂spring的常用注解

    spring传统做法是使用xml文件对bean进行注入和配置.通过使用spring提供的注解,可以极大的降低配置xml文件的繁琐.本文将介绍常用的注解. 一@Autowired Autowired意为 ...

  3. 一文搞懂Spring AOP源码底层原理

    一.什么是AOP 与OOP对比,AOP是处理一些横切性问题,这些横切性问题不会影响到主逻辑实现的,但是会散落到代码的各个部分,难以维护.一键获取源码地址spring aop面试题 AOP就是把这些问题 ...

  4. 一文搞懂RNN(循环神经网络)

    基础篇|一文搞懂RNN(循环神经网络) https://mp.weixin.qq.com/s/va1gmavl2ZESgnM7biORQg 神经网络基础 神经网络可以当做是能够拟合任意函数的黑盒子,只 ...

  5. 一文搞懂 Python 的 import 机制

    一.前言 希望能够让读者一文搞懂 Python 的 import 机制 1.什么是 import 机制? 通常来讲,在一段 Python 代码中去执行引用另一个模块中的代码,就需要使用 Python ...

  6. python语言语句快的标记是什么_一文搞懂Python程序语句

    原标题:一文搞懂Python程序语句 程序流 Python 程序中常用的基本数据类型,包括: 内置的数值数据类型 Tuple 容器类型 String 容器类型 List 容器类型 自然的顺序是从页面或 ...

  7. 一文搞定 Spring Data Redis 详解及实战

    转载自  一文搞定 Spring Data Redis 详解及实战 SDR - Spring Data Redis的简称. Spring Data Redis提供了从Spring应用程序轻松配置和访问 ...

  8. 一文搞懂 Java 线程中断

    转载自   一文搞懂 Java 线程中断 在之前的一文<如何"优雅"地终止一个线程>中详细说明了 stop 终止线程的坏处及如何优雅地终止线程,那么还有别的可以终止线程 ...

  9. 一张图搞懂Spring bean的完整生命周期

    转载自 一张图搞懂Spring bean的完整生命周期 一张图搞懂Spring bean的生命周期,从Spring容器启动到容器销毁bean的全过程,包括下面一系列的流程,了解这些流程对我们想在其中任 ...

最新文章

  1. Ubuntu 和 Redhat / Fedora 服务管理命令对比表(附Fedora16新的服务管理工具systemctl )...
  2. AndroidStudio直接通过gradle无mk编译生成so
  3. 八皇后java_经典八皇后问题:Java语言
  4. 1.16 快速排序法(Quicksort)
  5. .NET开发框架(九)-NLB网络负载平衡配置实战(视频)
  6. linux网络体系架构
  7. 用树形算法思想去使用思维导图\树形图\鱼骨图
  8. 计算机桌面任务栏窗口对话框菜单的功能,电脑下方的任务栏不显示怎么办 在任务栏和开始菜单属性对话框...
  9. 项目管理四要素是什么?
  10. 华中科技大学计算机考研信息汇总
  11. 读浅墨博客 十一 笔记
  12. 网页设计与网站规划 作业05 电影宣传效果
  13. 生成彩色二维码(渐变色、插入图片和文字)
  14. android系统system镜像解包打包制作过程
  15. FTP如何用计算机名,ftp服务器使用虚拟主机名(怎么设置ftp服务器)
  16. APS科普:如何缩短制造提前期?
  17. 分布式持久内存文件系统Octopus(ATC-17 )分析(二)
  18. Echarts 3D地图图表
  19. Python OpenCV开发MR智能人脸识别打卡系统(三、工具模块设计)
  20. 软件项目外包的优缺点

热门文章

  1. python寻找list中最大值、最小值并返回其所在位置
  2. web前端【第三篇】CSS选择器
  3. c# 中dynamic的使用
  4. git、cocoapod组件化开发常用命令
  5. android基础知识(2)
  6. [源码]天骄天下个人网站系统(三个月倾情打造)
  7. windows下使用conda命令在anaconda环境中安装caffe
  8. 统计xml文件中的标签出现框数及出现过的图片数
  9. 在gcp终端中使用ssh连接到本地机器
  10. mysql 1143_ERROR 1143 (42000): SELECT command denied to user