JPA这部分内容上手很容易,但是涉及到的东西还是挺多的,网上大部分关于 JPA 的资料都不是特别齐全,大部分用的版本也是比较落后的。另外,我下面讲到了的内容也不可能涵盖所有 JPA 相关内容,我只是把自己觉得比较重要的知识点总结在了下面。我自己也是参考着官方文档写的,官方文档非常详细了,非常推荐阅读一下。这篇文章可以帮助对 JPA 不了解或者不太熟悉的人来在实际项目中正确使用 JPA。

1.相关依赖

我们需要下面这些依赖支持我们完成这部分内容的学习:





org.springframework.boot

spring-boot-starter-web





org.springframework.boot

spring-boot-starter-data-jpa





mysql

mysql-connector-java

runtime





org.projectlombok

lombok

true





org.springframework.boot

spring-boot-starter-test

test

2.配置数据库连接信息和JPA配置

下面的配置中需要单独说一下 spring.jpa.hibernate.ddl-auto=create这个配置选项。

这个属性常用的选项有四种:

create:每次重新启动项目都会重新创新表结构,会导致数据丢失

create-drop:每次启动项目创建表结构,关闭项目删除表结构

update:每次启动项目会更新表结构

validate:验证表结构,不对数据库进行任何更改

但是,一定要不要在生产环境使用 ddl 自动生成表结构

一般推荐手写 SQL 语句配合 Flyway 来做这些事情。

spring.datasource.url=jdbc:mysql://localhost:3306/springboot_jpa?useSSL=false&serverTimezone=CTT

spring.datasource.username=root

spring.datasource.password=123456

打印出 sql 语句

spring.jpa.show-sql=true

spring.jpa.hibernate.ddl-auto=create

spring.jpa.open-in-view=false

创建的表的 ENGINE 为 InnoDB

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL55Dialect

3.实体类

我们为这个类添加了 @Entity 注解代表它是数据库持久化类,还配置了主键 id。

import lombok.Data;

import lombok.NoArgsConstructor;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

@Entity

@Data

@NoArgsConstructor

public class Person {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true)
private String name;
private Integer age; public Person(String name, Integer age) {
this.name = name;
this.age = age;
}

}

如何检验你是否正确完成了上面 3 步?

很简单,运行项目,查看数据如果发现控制台打印出创建表的 sql 语句,并且数据库中表真的被创建出来的话,说明你成功完成前面 3 步。

控制台打印出来的 sql 语句类似下面这样:

drop table if exists person

CREATE TABLE person (

id bigint(20) NOT NULL AUTO_INCREMENT,

age int(11) DEFAULT NULL,

name varchar(255) DEFAULT NULL,

PRIMARY KEY (id)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

alter table person add constraint UK_p0wr4vfyr2lyifm8avi67mqw5 unique (name)

4.创建操作数据库的 Repository 接口

@Repository

public interface PersonRepository extends JpaRepository<Person, Long> {

}

首先这个接口加了 @Repository 注解,代表它和数据库操作有关。

另外,它继承了 JpaRepository<Person, Long>接口,而JpaRepository<Person, Long>长这样:

@NoRepositoryBean

public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor {

List 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);

}

这表明我们只要继承了JpaRepository<T, ID> 就具有了 JPA 为我们提供好的增删改查、分页查询以及根据条件查询等方法。

4.1 JPA 自带方法实战

增删改查

1.保存用户到数据库

Person person = new Person("SnailClimb", 23);

personRepository.save(person);

save()方法对应 sql 语句就是:insert into person (age, name) values (23,"snailclimb")

2.根据 id 查找用户

Optional personOptional = personRepository.findById(id);

findById()方法对应 sql 语句就是:select * from person p where p.id = id

3.根据 id 删除用户

personRepository.deleteById(id);

deleteById()方法对应 sql 语句就是:delete from person where id=id

4.更新用户

更新操作也要通过 save()方法来实现,比如:

Person person = new Person("SnailClimb", 23);

Person savedPerson = personRepository.save(person);

// 更新 person 对象的姓名

savedPerson.setName("UpdatedName");

personRepository.save(savedPerson);

在这里 save()方法相当于 sql 语句:update person set name="UpdatedName" where id=id

  1. 带条件的查询

    下面这些方法是我们根据 JPA 提供的语法自定义的,你需要将下面这些方法写到 PersonRepository 中。

    假如我们想要根据 Name 来查找 Person ,你可以这样:

    Optional findByName(String name);

    如果你想要找到年龄大于某个值的人,你可以这样:

    List findByAgeGreaterThan(int age);

4.2 自定义 SQL 语句实战

很多时候我们自定义 sql 语句会非常有用。

根据 name 来查找 Person:

@Query("select p from Person p where p.name = :name")

Optional findByNameCustomeQuery(@Param("name") String name);

Person 部分属性查询,避免 select *操作:

@Query("select p.name from Person p where p.id = :id")

String findPersonNameById(@Param("id") Long id);

根据 id 更新Person name:

@Modifying

@Transactional

@Query("update Person p set p.name = ?1 where p.id = ?2")

void updatePersonNameById(String name, Long id);

4.3 创建异步方法

如果我们需要创建异步方法的话,也比较方便。

异步方法在调用时立即返回,然后会被提交给TaskExecutor执行。当然你也可以选择得出结果后才返回给客户端。如果对 Spring Boot 异步编程感兴趣的话可以看这篇文章:《新手也能看懂的 SpringBoot 异步编程指南》 。

@Async

Future findByName(String name);

@Async

CompletableFuture findByName(String name);

5.测试类

测试类:

@SpringBootTest

@RunWith(SpringRunner.class)

public class PersonRepositoryTest {

@Autowired

private PersonRepository personRepository;

private Long id;

/**
* 保存person到数据库
*/
@Before
public void setUp() {
assertNotNull(personRepository);
Person person = new Person("SnailClimb", 23);
Person savedPerson = personRepository.saveAndFlush(person);// 更新 person 对象的姓名
savedPerson.setName("UpdatedName");
personRepository.save(savedPerson); id = savedPerson.getId();
} /**
* 使用 JPA 自带的方法查找 person
*/
@Test
public void should_get_person() {
Optional<Person> personOptional = personRepository.findById(id);
assertTrue(personOptional.isPresent());
assertEquals("SnailClimb", personOptional.get().getName());
assertEquals(Integer.valueOf(23), personOptional.get().getAge()); List<Person> personList = personRepository.findByAgeGreaterThan(18);
assertEquals(1, personList.size());
// 清空数据库
personRepository.deleteAll();
} /**
* 自定义 query sql 查询语句查找 person
*/ @Test
public void should_get_person_use_custom_query() {
// 查找所有字段
Optional<Person> personOptional = personRepository.findByNameCustomeQuery("SnailClimb");
assertTrue(personOptional.isPresent());
assertEquals(Integer.valueOf(23), personOptional.get().getAge());
// 查找部分字段
String personName = personRepository.findPersonNameById(id);
assertEquals("SnailClimb", personName);
System.out.println(id);
// 更新
personRepository.updatePersonNameById("UpdatedName", id);
Optional<Person> updatedName = personRepository.findByNameCustomeQuery("UpdatedName");
assertTrue(updatedName.isPresent());
// 清空数据库
personRepository.deleteAll();
}

}

  1. 总结

    本文主要介绍了 JPA 的基本用法:

    使用 JPA 自带的方法进行增删改查以及条件查询。

    自定义 SQL 语句进行查询或者更新数据库。

    创建异步的方法。

    在下一篇关于 JPA 的文章中我会介绍到非常重要的两个知识点:

    基本分页功能实现

    多表联合查询以及多表联合查询下的分页功能实现。

SPringBootJPA的使用快速开发的更多相关文章

  1. arcpy+PyQt+py2exe快速开发桌面端ArcGIS应用程序

    前段时间有一个项目,大体是要做一个GIS数据处理工具. 一般的方法是基于ArcObjects来进行开发,因为我对ArcObjects不太熟悉,所以就思考有没有其他简单快速的方法来做. 在查看ArcGI ...

  2. 快速开发Grunt插件----压缩js模板

    前言 Grunt是一款前端构建工具,帮助我们自动化搭建前端工程.它可以实现自动对js.css.html文件的合并.压缩等一些列操作.Grunt有很多插件,每一款插件实现某个功能,你可以通过npm命名去 ...

  3. winform快速开发平台->让有限的资源创造无限的价值!

    最近一直在维护一套自己的快速开发平台. 主要应对针对C/S架构下的项目.然而对winform这快,还真没有看到过相对好的快速开发平台, 何为快速,在博客园逛了了好久, 预览了很多通用权限管理系统. 确 ...

  4. winform快速开发平台 -> 通用权限管理之动态菜单

    这几个月一直忙APP的项目,没来得及更新项目,想想该抽出时间整理一下开发思路,跟大家分享,同时也希望得到宝贵的建议. 先说一下我们的权限管理的的设计思路,首先一个企业信息化管理系统一定会用到权限管理, ...

  5. winform快速开发平台 -> 工作流组件(仿GooFlow)

    对于web方向的工作流,一直在用gooflow对于目前我的winform开发平台却没有较好的工作流组件.  针对目前的项目经验告诉我们.一个工作流控件是很必要的. 当然在winform方面的工作流第三 ...

  6. winform快速开发平台 -> 快速绑定ComboBox数据控件

    通常我们在处理编辑窗体时.往往会遇到数据绑定.例如combobox控件绑定数据字典可能是我们经常用到的.然而在我的winform快速开发平台中我是如何处理这个频繁的操作呢? 首先,我们要绑定combo ...

  7. winform快速开发平台 -> 基础组件之分页控件

    一个项目控件主要由及部分的常用组件,当然本次介绍的是通用分页控件. 处理思想:我们在处理分页过程中主要是针对数据库操作. 一般情况主要是传递一些开始位置,当前页数,和数据总页数以及相关关联的业务逻辑. ...

  8. 使用GizwitsOpenAPI,快速开发轻应用

    导读:使用机智云提供的Open API(Http / WebSocket),可以快速开发网页或微信应用等基于html的轻应用,用于管理和控制智能设备.机智云 Open API 主要帮助开发者通过 HT ...

  9. CYQ.Data 快速开发EasyUI

    EasyUI: 前端UI框架之一, 相对ExtJs来说,算是小了,这两天,抽空看了下EasyUI的相关知识,基本上可以和大伙分享一下: 官网: http://www.jeasyui.com/ 学习的话 ...

随机推荐

  1. Python的基础知识,不同于其他编程语言

    1.字符串拼接可以不使用+号 name = "this " "is " "a " "string" 2.使用''' ‘’ ...

  2. Follow somebody

    networkersdiary A personnel blog with Network Engineering articles https://networkersdiary.com/cisco ...

  3. java web 学生信息录入

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  4. WPS/office使用技巧系列

    一 WPS中如果要对比2个文档,不想以标签形式打开而是以多窗口形式,该怎么操作? 点击WPS左上角的蓝色或绿色框-->选项->->视图->勾选在任务栏中显示所有窗口,恢复书签模 ...

  5. Update(Stage4):sparksql:第1节 SparkSQL_使用场景_优化器_Dataset & 第2节 SparkSQL读写_hive_mysql_案例

    目标 SparkSQL 是什么 SparkSQL 如何使用 Table of Contents 1. SparkSQL 是什么 1.1. SparkSQL 的出现契机 1.2. SparkSQL 的适 ...

  6. Django 中的时区

    Django 中的时区 在现实环境中,存在有多个时区.用户之间很有可能存在于不同的时区,并且许多国家都拥有自己的一套夏令时系统.所以如果网站面向的是多个时区用户,只以当前时间为标准开发,便会在时间计算 ...

  7. 九、web.xml理解

    1.web.xml文件在每个web工程不是必须要有的:     web.xml文件是用来初始化配置信息:比如Welcome页面.servlet.servlet-mapping.filter.liste ...

  8. 最全BT磁力搜索引擎索引(整理分享,每日更新)

    btaa.xyz:http://www.veee.xyz/(可以访问,知名的BT磁力搜索,资源多,建议手机访问) 以下无法访问 idope.se:https://idope.se/(无法访问,资源丰富 ...

  9. SD-WAN功能

    SD-WAN功能 在这些底层技术的基础之上,SD-WAN最终能为客户提供哪些创新型服务.解决哪些具体问题? 统一管理与监控:SD-WAN整合了路由器.防火墙.DPI检测.广域网加速等功能,确保企业真正 ...

  10. [转]Java监听器的原理与实现

    原文链接 监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动.监听器其实就是一个实现特定接口的普通java程序,这个程序专门用 ...