前言

(一). JPA的介绍

(二). 配置使用JPA

(三). 案例实战

 

上篇文章为大家讲述了 Spring Boot中 Bootstrap和AngularJS的使用;本篇文章接着上篇内容继续为大家介绍SpringBoot中 JPA的使用。

(一). JPA的介绍

Jpa是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

jpa使用起来非常方便和使用,jpa具有什么优势?
1,标准化
JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。

2,容器级特性的支持
JPA框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。

3,简单方便
JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。

4,查询能力
JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。

5,高级特性
JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。

jpa是基于注解的使用,那么他都有哪些注解呢?

@Entity 声明类为实体或表。
@Table 声明表名。
@Basic 指定非约束明确的各个字段。
@Embedded 指定类或它的值是一个可嵌入的类的实例的实体的属性。
@Id 指定的类的属性,用于识别(一个表中的主键)。
@GeneratedValue 指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。
@Transient 指定的属性,它是不持久的,即:该值永远不会存储在数据库中。
@Column 指定持久属性栏属性。
@SequenceGenerator 指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列。
@TableGenerator 指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表。
@AccessType 这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。
@JoinColumn 指定一个实体组织或实体的集合。这是用在多对一和一对多关联。
@UniqueConstraint 指定的字段和用于主要或辅助表的唯一约束。
@ColumnResult 参考使用select子句的SQL查询中的列名。
@ManyToMany 定义了连接表之间的多对多一对多的关系。
@ManyToOne 定义了连接表之间的多对一的关系。
@OneToMany 定义了连接表之间存在一个一对多的关系。
@OneToOne 定义了连接表之间有一个一对一的关系。
@NamedQueries 指定命名查询的列表。
@NamedQuery 指定使用静态名称的查询。

 

(二). 配置使用JPA

1,使用Spring Data JPA 建立数据访问层只需要集成 JpaRepository的接口:
代码如下:
 

public interface PersonRepository extends JpaRepository<Person,Long>{
}

2,继承 JpaRepository接口后我们就可以使用下面几种数据访问的方法:

List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAll(Iterable<ID> var1);
<S extends T> List<S> save(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);

3,使用Spring Data JPA可以通过@EnableJpaRepositories注解来开启Spring Data Jpa的支持, 接收到的value参数用来扫描数据访问层所在包下的数据访问的接口定义:
 

@Configuration
@EnableJpaRepositories(“org.cxzc.myyoung”)
public class JpaConfiguration{
 @Bean
 public EntityManagerFactory entityManageFactory(){
}
}

4,定义查询方法

#常规查询
根据属性名称来定义查询方法
 

public interface PersonResopitory extends JpaRepository <Person,Long> {
  //通过名称相等查询,参数为name
  //相当于 select p from Person p where p.name=?1
  List<Person> findByName(String name)
  //相当于 select p from Person p where p.name like ?1
  List<Person> findByNameLike(String name)
}

#限制结果查询

结果数量是使用 top和first 扥关键字来实现的,例如:
 

public interface PersonResopitory extends JpaRepository <Person,Long> {
  //获得符合查询条件的前10条数据
  List<Person> findFirst10ByName(String name)
}

#使用 JPA的NamedQuery查询
Spring Data JPA支持使用 JPA的NamedQuery 来定义查询方法,即一个名称映射一个查询语句
定义如下:

@Entity
@NamedQuery(name = "Person.findName"),
  query = "select p from Person p where p.name = ?1"
 public class Person{
 }

使用如下

public interface PersonResopitory extends JpaRepository <Person,Long> {
  //获我们使用NamedQuery 里面定义的查询语句,不是根据名称查询
  List<Person> findByName(String name)
}

#使用@Query查询
Spring Data Jpa还支持使用@Query注解在接口的方法上实现查询,例如:

public interface PersonResopitory extends JpaRepository <Person,Long> {
 @Query("select p from Person p where p.address = ?1")
  List<Person> findByAddress(String address)
}

(三). 案例实战

好了,上面说了 JPA 和有关的一些使用方法,充分体现了 Spring Data JPA这样一个东东,在使用中 可以减少我们使用JPA时的代码量。

我们通过一个实例来看看 JPA怎么运用在 Spring Boot项目开发中。

1. 创建项目
创建项目很简单 我们只需要选择 JPA的依赖就行了
 

springboot jpa 配置 springboot jpa save_Spring Boot

 

springboot jpa 配置 springboot jpa save_Spring Boot_02

 

2, 添加数据库依赖
项目创建成功之后,我们使用MySql做演示,因此还需要添加MySql驱动,在pom.xml文件中添加数据库依赖,如下:

 

<dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.40</version>
    </dependency>

3,配置数据库属性
我们使用数据库 首先要配置数据库的属性
 

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springbootjpa?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jackson.serialization.indent_output=true
1.第一行表示驱动的名称,这个和具体的数据库驱动有关,
视情况而定,我这里使用了MySql数据库,
所以驱动名为com.mysql.jdbc.Driver
2.第二行表示数据库连接地址,数据库名,编码等
3.第三四行表示数据库连接的用户名和密码
4.第五行则配置了实体类维护数据库表结构的具体行为,
update表示当实体类的属性发生变化时,表结构跟着更新,
这里我们也可以取值create,这个create表示启动的时候删除上一次生成的表,
并根据实体类重新生成表,这个时候之前表中的数据就会被清空;
还可以取值create-drop,这个表示启动时根据实体类生成表,
但是当sessionFactory关闭的时候表会被删除;
validate表示启动时验证实体类和数据表是否一致;none表示啥都不做。
5.第六行表示hibernate在操作的时候在控制台打印真实的sql语句
6.第七行表示格式化输出的json字符串

4,定义映射实体类
接下来,定义相应的实体类,在Project启动时,系统会根据实体类创建相应的数据表,如下:

package org.cxzc.myyoung.springboot_jpa;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
@Entity
@NamedQuery(name = "Person.withNameAndAddressNamedQuery",
        query = "select p from Person p where p.name=?1 and p.address=?2")
public class Person {
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    private Integer age;
    private String address;
    public Person() {
    }
    public Person(Long id, String name, Integer age, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}

 

1,@Entity注解,这个表示这是一个和数据库表映射的实体类

2,在属性id上我们添加了@Id注解,表示该字段是一个id,@GeneratedValue注解则表示该字段自增。

3,@NamedQuery注解表示一个NamedQuery查询,这里一个名称代表一个查询语句,我们一会可以在控制器中直接调用@NamedQuery中的withNameAndAddressNamedQuery方法,该方法代表的查询语句是select p from Person p where p.name=?1 and p.address=?2。

 

5,定义数据访问接口

package org.cxzc.myyoung.springboot_jpa;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface PersonRepository extends JpaRepository<Person, Long> {
    List<Person> findByAddress(String name);
    Person findByNameAndAddress(String name, String address);
    @Query("select p from Person p where p.name=:name and p.address=:address")
    Person withNameAndAddressQuery(@Param("name") String name, @Param("address") String address);
    Person withNameAndAddressNamedQuery(String name, String address);
}

1. 使用方法名查询,接收一个那么参数,返回列表

2. 使用方法名称查询,接收name和address 返回单个对象3. 使用@Query查询 参数安装名称绑定

4. 使用@NamedQuery 查询 请注意实体类中做的 定义

6,控制类的添加

数据访问接口我们已经添加了,接下来就是添加一个 Controller,我们写一个 用来测试一下上文中的数据访问接口是否正确,如下:
 

package org.cxzc.myyoung.springboot_jpa;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class DataController {
    @Autowired
    PersonRepository personRepository;
    @RequestMapping("/save")
    public Person save(String name,String address,Integer age) {
        Person person = personRepository.save(new Person(null, name, age, address));
        return person;
    }
    @RequestMapping("/q1")
    public List<Person> q1(String address) {
        List<Person> people = personRepository.findByAddress(address);
        return people;
    }
    @RequestMapping("/q2")
    public Person q2(String name, String address) {
        Person people = personRepository.findByNameAndAddress(name, address);
        return people;
    }
    @RequestMapping("/q3")
    public Person q3(String name, String address) {
        Person person = personRepository.withNameAndAddressQuery(name, address);
        return person;
    }
    @RequestMapping("/q4")
    public Person q4(String name, String address) {
        Person person = personRepository.withNameAndAddressNamedQuery(name, address);
        return person;
    }
//    @RequestMapping("/sort")
//    public List<Person> sort() {
//        List<Person> people = personRepository.findAll(new Sort(Sort.Direction.ASC, "age"));
//        return people;
//    }
    @RequestMapping("/page")
    public Page<Person> page(int page, int size){
        Page<Person> all = personRepository.findAll(PageRequest.of(page, size));
        return all;
    }
    @RequestMapping("/all")
    public List<Person> all(){
        return personRepository.findAll();
    }
}

7,运行效果

我们这里只截图演示一个 ,小伙伴运行项目 自行测试。

springboot jpa 配置 springboot jpa save_springboot jpa 配置_03

 

ok,本篇内容到这里就完成了,如果小伙伴还有疑问,可以关注我,我们一起进步