Spring Boot JPA 连接数据库

何为JPA

JPA全称Java Persistence API,是Sun官方提出的一种ORM规范!

对于Sun官网而言, 一是想简化现有Java EE和Java SE应用开发工作。 二是想整合ORM技术,实现天下归一。

对于JPA规范,都在包路径:javax.persistence.*下,像一些常用的如:@Entity、@Id及@Transient都在此路径下。这些也是一些现在市面上常用的ORM一些约定俗成的注解了。

简单来说,JPA是一套规范。所以使用Jpa的一个好处是,可以更换实现而不必改动太多代码。

JPA与hibernate的关系 

JPA规范本质上就是一种ORM规范,注意不是ORM框架——因为JPA并未提供ORM实现,它只是制订了一些规范,提供了一些编程的API接口,但具体实现则由服务厂商来提供实现。  

JPA和Hibernate的关系就像JDBC和JDBC驱动的关系,JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现。JPA怎么取代Hibernate呢?JDBC规范可以驱动底层数据库吗?答案是否定的,也就是说,如果使用JPA规范进行数据库操作,底层需要hibernate作为其实现类完成数据持久化工作。  

何为Sping-data-jpa

Spring Data JPA是 Spring Data 的一个子项目, 它通过提供基于 JPA的 Repository 极大地减少了 JPA作为数据访问方案的代码量。Spring Data JPA是Spring基于Hibernate开发的一个JPA框架。可以极大的简化JPA的写法,可以在几乎不用写具体代码的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一些常用的功能。

下面将通过一个完整的例子来说明JPA的使用方式

Spring Data JPA提供的接口,也是Spring Data JPA的核心概念:

  1. Repository:最顶层的接口,是一个空的接口,目的是为了统一所有Repository的类型,且能让组件扫描的时候自动识别。
  2. CrudRepository :是Repository的子接口,提供CRUD的功能
  3. PagingAndSortingRepository:是CrudRepository的子接口,添加分页和排序的功能
  4. JpaRepository:是PagingAndSortingRepository的子接口,增加了一些实用的功能,比如:批量操3作等。
  5. JpaSpecificationExecutor:用来做负责查询的接口
  6. Specification:是Spring Data JPA提供的一个查询规范,要做复杂的查询,只需围绕这个规范来设置查询条件即可。

SpringBoot集成Spring-data-jpa

添加相关依赖
添加spring-boot-starter-data-jpa依赖:

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

修改属性配置文件

在属性配置文件中添加 JPA 相关属性,注意这些并非必须,我们如果只添加dataSource 的 url\username\password\driver-class-name 也可以正常使用,有关JPA的其他配置都是可选的。

可以在application.yml文件中配置配置数据源:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1/test?characterEncoding=utf-8&useUnicode=true&serverTimezone=UTC&useSSL=false&autoReconnect=true
    username: root
    password: 9958

  jpa:
    database-platform: org.hibernate.dialect.MySQL5Dialect
    hibernate:
#      ddl-auto: create #每次启动都会重新创建
      ddl-auto: update #如果表中有数据就不会重新创建
    show-sql: true

也可以在application.properties文件配置mysql的驱动类,数据库地址,数据库账号、密码信息

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.url=jdbc:mysql://127.0.0.1/test?characterEncoding=utf8&serverTimezone=UTC

spring.datasource.username=root

spring.datasource.password=9958

spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect

spring.jpa.hibernate.ddl-auto=update

spring.jpa.show-sql=true

注意,如果通过jpa在数据库中建表,需要将jpa.hibernate.ddl-auto改为create,建完表之后要改为update,否则每次重启工程都会删除表并新建。spring.jap.hibernate.ddl-auto有四个值:

  1. create: 每次加载 hibernate 时都会删除上一次的生成的表,然后根据你的 model 类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
  2. create-drop :每次加载 hibernate 时根据 model 类生成表,但是 sessionFactory 一关闭,表就自动删除。
  3. update:最常用的属性,第一次加载 hibernate 时根据 model 类会自动建立起表的结构(前提是先建立好数据库),以后加载 hibernate 时根据 model 类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
  4. validate :每次加载 hibernate 时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。

创建实体类

传统上,JPA实体类在persistence.xml文件中指定的。使用Spring Boot,这个文件是没有必要的,因为它使用“实体扫描”,默认情况下主配置 @EnableAutoConfiguration 或 @SpringBootApplication 下面的所有包都将会被扫描。任何使用注解 @Entity, @Embeddable 或 @MappedSuperclass 的类都将被管理。

/**
 * 通过@Entity 表明是一个映射的实体类, @Id表明id, @GeneratedValue 字段自动生成
 */
@Entity
public class Girl {
    @Id
    @GeneratedValue
    private int id;
    private String name;
    private int age;

...  省略getter setter
}

Entity 中不映射成列的字段得加 @Transient 注解,不加注解也会映射成列

定义数据访问层

使用 Spring Data JPA建立数据访问层十分简单, 只需定义一个继承 JpaRepository 的接口即可,定义如下:

public interface GirlRepository extends JpaRepository<Girl, Integer> {

}

继承 JpaRepository 接口意味着我们默认已经有了下面的数据访问操作方法:

@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);
}

定义查询方法

( 1 ) 根据属性名査询

Spring Data JPA支持通过定义在 Repository 接口中的方法名来定义査询,而方法名是根据实体类的属性名来确定的 。

1)常规查询。根据属性名来定义査询方法,示例如下:

/*通过年龄相等查询,参数为age
* 相当于JPQL:select g from Girl g whrer g.age=?1
*/
List<Girl> findByAge(Integer age);
/*通过名字like查询,参数为name
*相当于JPQL:select g from Girl g whrer g.name like ?1
*/
List<Girl> findByNameLike(String name);

从代码可以看出,这里使用了 findBy、 Like、 And这样的关键字。其中 findBy可以用 find、read、 readBy、 query、 queryBy、 get、 getBy来代替。

而 Like和 and这类査询关键字, 如表

 

2)限制结果数量。结果数量是用 top和 first关键字来实现的,例如:

List<Girl> findFirst10Byname(String name);

List<Girl> findTop20Byname(String name);

(2)使用 JPA的NamedQuery查询

spring Data JpA支持用 JPA的 NameQuery 来定义査询方法,即一个名称映射一个查询语句,在实体类中:

@Entity
@NamedQuery(name = "Girl.findByName", query = "select g from Girl g  where g.name=?1")
public class Girl {
..}

调用这条查询语句的方法:

public interface GirlRepository extends JpaRepository<Girl, Integer> {
    /*使用NamedQuery里定义的查询语句,而不是根据方法名称查询*/
    List<Girl> findByName(String name);

(3)使用@Query 査询

1)使用参数索引 。 Spring Data JPA还支持用@Query注解在接口的方法上实现査询,例如:

@Query("select g from Girl g where g.id=?1")

Optional<Girl> findById(Integer name);

2)使用命名参数。上面的例子是使用参数的索引号来査询的,在 Spring Data JPA里还支持在语句里用名称来匹配査询参数

@Query("select g from Girl g where g.id=:name and g.age=:age")

Optional<Girl> findByName(@Param("name") String name,@Param("age") int age);

3 ) 更新査询。 Sprmg Data JPA支持@Modifying和@Query 注解组合来事件更新查询, 例如

@Modifying
@Transactional
@Query("update Girl g set g.name=?1")
int setName(String name);

其中返回值int表示更新语句影响的行数。

(4)排序与分页

Spring Data JPA充分考虑了在实际开发中所必须的排序和分页的场景,为我们提供了Sort类以及Page接口和Pageable接口

1)定义:

//使用排序

List<Girl> findByName(String name, Sort sort);

//使用分页

List<Girl> findByName(String name, Pageable pageable);

2)使用

//使用排序
List<Girl> findByName(String name, Sort sort);
//使用分页
List<Girl> findByName(String name, Pageable pageable);
2)使用
List<Girl> list1=girlRepository.findByName(name,Sort.by(Sort.Direction.ASC,"age"));
List<Girl> list2=girlRepository.findByName(name, PageRequest.of(0,10));

具体的测试和代码,我就不完全粘贴了,想看的可以直接看我的代码

 

源码

参考:

http://blog.csdn.net/catoop/article/details/50508397

http://blog.csdn.net/forezp/article/details/70545038

http://www.ityouknow.com/springboot/2016/08/20/spring-boot-jpa.html

https://gitchat.csdn.net/columnTopic/5ab9c2e0c864031e9f8302dc

https://my.oschina.net/xiedeshou/blog/2350428

https://blog.csdn.net/u010412719/article/details/70147824

https://blog.csdn.net/u013030980/article/details/78135335

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值