一文搞懂 Spring JPA
haoteby 2025-01-03 16:09 11 浏览
作者 | 阿文
责编 | 屠敏
什么是 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 {
@Autowired
JdbcTemplate 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 {
@Autowired
UserDao 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 {
@Autowired
UserMapper 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
@GeneratedValue
private long id;
@Column(able = false, unique = true)
private String userName;
@Column(able = false)
private String password;
@Column(able = 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 表示开启事务防止出现脏数据。
……
@Autowired
private UserRepository userRepository;
@Test
@Transactional
public 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 的介绍。
相关推荐
- 能跑源码,还提供数据集:这里有一个入门企业级验证码识别项目
-
机器之心专栏作者:kerlomz网上关于验证码识别的开源项目众多,但大多是学术型文章或者仅仅是一个测试demo,那么企业级的验证码识别究竟是怎样的呢?1.前言网上关于验证么识别的开源项目众多,但大...
- kdj源码_kdj源码公式描述
-
N:=9;M1:=3;M2:=3;...
- QT实现抖动文字和滚动文字,附源码
-
前言不知道大家有没有发现今天的文章有什么不一样,哈哈,我自己胡拼乱凑弄了一个logo,好不好看就先不说了,最起码萌萌哒...当然这不是今天的重点,在做logo的时候,我原本想让文字动起来的,奈何技术有...
- 我试图通过这篇文章告诉你,这行源码有多牛逼。
-
你好呀,我是歪歪。这次给你盘一个特别有意思的源码,正如我标题说的那样:看懂这行源码之后,我不禁鼓起掌来,直呼祖师爷牛逼。...
- 想了解Python源代码加密吗?现总结如下5大加密混淆手段!
-
我们在进行...
- Android系统基础(03) Android系统源码下载
-
常规官方网站说明:Android源码官方网站为(google你懂的):https://source.android.com官网参考链接,对应的tag(tag是一种标签,我们可以根据tag来判断下载的...
- 真香,Python爬取B站弹幕原来如此简单,源码已附在文末
-
B站的弹幕区一直是人才圣地。今天我就用python来手把手教大家爬取B站排行榜热门视频,Python爬取视频也可以如此简单。...
- 最详细的 maven 教程,可以收藏_maven步骤
-
链接|cnblogs.com/hzg110/p/6936101.html正文目前所有的项目都在使用maven,可是一直没有时间去整理学习,这两天正好有时间,好好的整理一下。...
- Python黑科技-VIP视频破解源码分享
-
《利用Python制作自己的VIP视频解析软件》想看的电视剧更新了还要充VIP?喜欢的电影你是VIP还得付费?学了Python哪要这些花里胡哨的,打开我自己的VIP付费视频解析软件,想怎么看就怎么看!...
- 抖音无水印解析网站源码_抖音无水印解析平台
-
链接:https://share.weiyun.com/59Ah44S密码:hv4dm7上传到主机解压不用安装,直接打开域名就可以了原文地址:https://www.xigsc.com/post/...
- 「电脑知识」USBOS 3.0 v2022.1.24 超级PE启动维护工具标准增强版
-
前几天一直在发PE类工具就是为了制作U盘PE启动重装系统教程的,今天小编继续分享有一篇关于pe的之前小编发布过一款微PE工具箱,今天发布另外一个无任何流氓行为功能超级强大虽然体积大了一点,但是这个...
- 模版网站建设制作的八步流程_模板的网站
-
模版网站比较简单,一般我们按照如下流程就可以制作出来。 一、网站定位: 在建站之前,一定要了解你要建的网站是什么。你必须考虑你网站的标题(关键词)、网站描述以及你想要建立的网站。 二、选择域...
- 求职季必备,这几个免费的个人简历模板网站,你可千万不要错过!
-
晃晃悠悠又到了春招的季节,相信一定有很多小伙伴趁着这个金三银四求职季,四处投递简历。这时候一个亮眼优秀的简历,可以很好的祝你吸引HR的注意。今天就把我珍藏很久的5个免费简历模板网站分享给大家,简历模板...
- 简约时尚作品博客商店网站HTML5模板源码
-
Meduza是简约时尚和现代的博客HTML模板,带商店电商元素的博客页面。考虑所有的作品集网站需求页可以设计一个旅游网站。原生响应设计HTML5和CSS3(台式机、平板电脑、手机…)简单,干净的和专业...
- 13 款免费样机网站合集,UI设计、产品设计、VI设计全都有!
-
俗话说得好,人靠衣装,在作完设计后不少设计师都会为自己的作品套一个「样机」好让设计看过去更加高端大气上档次!今天,我就总结了无论是UI设计、包装设计、服装设计、品牌设计、logo设计,都能用到...