欢迎大家来到IT世界,在知识的湖畔探索吧!
欢迎大家来到IT世界,在知识的湖畔探索吧!
前言
- JPA是 Java Persistence API 的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关 系,并将运行期的实体对象持久化到数据库中。
- 在ORM框架中,Hibernate是一支很大的部队,使用很广泛,也很方便,能力也很强,同时Hibernate也是和JPA整 合的比较良好,我们可以认为JPA是标准,事实上也是,JPA几乎都是接口,实现都是Hibernate在做,宏观上面看,在 JPA的统一之下Hibernate很良好的运行。
- 我们都知道Spring的强大,到目前为止,企业级应用Spring几乎是无所不能,无所不在,已经是事实上的标准了, 企业级应用不使用Spring的几乎没有。而Spring整合第三方框架的能力又很强,他要做的不仅仅是个最早的IOC容器这 么简单一回事,现在Spring涉及的方面太广,主要是体现在和第三方工具的整合上。而在与第三方整合这方面,Spring 希望把持久化这块内容也拿下。于是就有了Spring-data-这一系列包。包括,Spring-data-jpa,Spring-data- template,Spring-data-mongodb,Spring-data-redis,还有个民间产品,mybatis-spring,和前面类似,这是和 mybatis整合的第三方包,这些都是干的持久化工具干的事儿。
- 这里介绍Spring-data-jpa,表示与Jpa的整合
- SpringData
:其实SpringData就是Spring提供了一个操作数据的框架。而SpringData JPA只是SpringData框架下的一个基于JPA标准操作数据的模块,总得包括以下:
- ORM映射:支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系
- API:操作实体对象来执行CRUD操作
- 查询语言:通过面向对象而非面向数据库的查询语言(JPQL)查询数据,避免程序的SQL语句紧密耦合
- SpringDataJPA
:基于JPA的标准数据进行操作。简化操作持久层的代码。只需要编写接口就可以。
- 后面博主会陆续写出Jpa的关联关系和增删改查以及连表查询操作,欢迎关注
什么是Spring Data Jpa
Spring Data Jpa是Spring Data家族的一部分,Spring Data JPA相对于Java EE中的JPA,配置更简单,以轻量级的方式实现了部分在 EJB 容器环境下才具有的功能,将 EntityManager 的创建与销毁、事务管理等代码抽取出来,并由其统一管理,并且极大的简化了数据库访问层的代码。 Spring Data包含众多子项目除了JPA还有Spring Data MongoDB等等
SpringJpa 的运行原理
- SpringJPA 的全称是 Spring Data JPA 。其中JPA是 Java Persistence API 的缩写(Java持久化API),是SUN公司推出的一套接口,一套标准,Hibernate是一个具体的ORM的持久层框架(类似于Mybatis框架)实现了JPA接口 。
- Spring Data 是Spring开发团队提供的一套标准API和不同持久层整合技术实现。Spring Data 的出现就是为了简化、统一持久层的各种实现技术API。 (注:Spring Data 在项目里以 spring-data-commons 这个jar存在 )
- Spring Data JPA 既实现了 Spring Data 接口又实现了JPA接口,也是为了简化持久层的开发。 (注:Spring Data JPA 在项目里以 spring-data-jpa 这个jar存在)
SpringJpa 优点
- 提供统一的接口,可避免我们再次重复的编写基础的DAO类;
- 遵循JPA规范,同时也提供了灵活的数据访问方式;
- 通过方法名即可自动生成HQL语句;
- 通过接口自动注入实现类,实现非常简单。
Spring Data JPA 与 MyBatis 对比
Spring Data JPA 与 MyBatis 对比,实际上就是 Hibernate 与 MyBatis 的对比,具体如下:
从基本概念和框架目标上看,两个框架差别还是很大的。 hibernate是一个自动化更强、更高级的框架,毕竟在java代码层面上,省去了绝大部分sql编写,取而代之的是 用面向对象的方式操作关系型数据库的数据。 MyBatis则是一个能够灵活编写sql语句,并将sql的入参和查询结果映射成POJOs的一个持久层框架。所以,从表 面上看,hibernate能方便、自动化更强,而MyBatis 在Sql语句编写方面则更灵活自由。
注:至于这两个框架用哪一个,可以根据自己的掌握情况或者使用场景进行选择。我个人推荐使用Spring Data JPA,因为的确很简单,符合敏捷开发要求。
SpringBoot 引入 SpringDataJpa 依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
欢迎大家来到IT世界,在知识的湖畔探索吧!
在yml文件配置如下,按需索取
欢迎大家来到IT世界,在知识的湖畔探索吧!spring: datasource: url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false username: root password: root jpa: database: mysql database-platform: org.hibernate.dialect.MySQL5InnoDBDialect show-sql: true hibernate: ddl-auto: update # 一般使用update # create: 每次运行程序时,都会重新创建表,故而数据会丢失 # create-drop: 每次运行程序时会先创建表结构,然后待程序结束时清空表 # upadte: 每次运行程序,没有表时会创建表,如果对象发生改变会更新表结构,原有数据不会清空,只会更新(推荐使用) # validate: 运行程序会校验数据与数据库的字段类型是否相同,字段不同会报错 # none: 禁用DDL处理
这里贴出来博主的一些配置:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jmccms</groupId> <artifactId>Jmccms</artifactId> <version>0.0.1-SNAPSHOT</version> <name>Jmccms</name> <url>https://repo.spring.io/milestone</url> <description>CYJ:ChenYongJia 服务提供者Jmccms</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <!-- 项目属性配置信息 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <!--引入spring-boot 2.1.1.RELEASE ,SpringCloud的版本为 Greenwich.M3--> <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version> <mysql-connector>5.1.39</mysql-connector> <junit-version>4.12</junit-version> <druid>1.0.18</druid> <!--<activiti.version>6.0.0</activiti.version>--> </properties> <dependencies> <!-- 引入web依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- 引入AOP --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!--<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.3</version> </dependency>--> <!-- SpringCloud Eureka 注册中心依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!-- SpringCloud Hystrix 微服务容错监控组件:断路器,依赖隔离,服务降级,服务监控 依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <!-- 权限控制Spring-Oauth2.0的认证模式依赖暂时不用,由于一些注解和API从spring security5.0中移除,所以需要导入下面的依赖包 --> <!-- spring-cloud-starter-oauth2 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <!-- SpringCloud Feign 依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- Spring Boot JPA 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- 引入test测试依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Junit 单元测试 依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <!-- 引入redis数据库依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- 引入jdbc链接依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!-- 引入security权限依赖模块 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- 引入Thymeleaf模板 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- 引入mysql链接依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-connector}</version> </dependency> <!-- 引入 Lombok 依赖 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- Spring Boot devtools 热部署 依赖 --> <!--<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency>--> <!-- alibaba的fastjson工具 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.56</version> </dependency> <!-- 引入Gson --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency> <!-- 阿里开源EXCEL --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>1.1.2-beta5</version> </dependency> <!--<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>--> <!-- 用于字符串工具类 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <!--<version>3.8.1</version>--> <version>3.6</version> <scope>provided</scope> </dependency> <!-- 使用httpclient获取天气信息 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.8</version> </dependency> <!-- 引入工作流 --> <!--<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>${activiti.version}</version> </dependency>--> <!--<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-actuator</artifactId> <version>${activiti.version}</version> </dependency>--> <!--<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-rest</artifactId> <version>${activiti.version}</version> </dependency>--> <!-- 整合swagger2 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!-- 整合swagger-ui --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <!-- eu帮助类 --> <dependency> <groupId>eu.bitwalker</groupId> <artifactId>UserAgentUtils</artifactId> <version>1.21</version> </dependency> </dependencies> <!-- SpringCloud 所有子项目 版本集中管理.MS:统一所有SpringCloud依赖项目的版本 依赖 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <!-- SpringBoot 2.1.X 以上版本这样配置 --> <version>${spring-cloud.version}</version> <!-- <version>Dalston.RC1</version> --> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <!-- SpringBoot 项目打jar包的Maven插件 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> <!-- SpringBoot项目打包jar名称 --> <finalName>jmccms</finalName> </build> <!-- SpringCloud 官方远程仓库.MS:部分本地仓库和镜像仓库没有SpringCloud子项目依赖。 --> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
使用 Spring Data Jpa 增删改查(当然一般都和 lombok 结合使用)
第一步先创建你的数据库和配置文件保持一致,Jpa将自动帮你建表
欢迎大家来到IT世界,在知识的湖畔探索吧!package com.jmccms.entity; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.*; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; import org.hibernate.annotations.NotFound; import org.hibernate.annotations.NotFoundAction; import org.springframework.format.annotation.DateTimeFormat; import javax.persistence.*; import java.io.Serializable; import java.sql.Timestamp; import java.util.Date; import java.util.HashSet; import java.util.Set; / * @Description: 用户类 * @BelongsProject: Jmccms * @BelongsPackage: com.jmccms.entity * @Author: ChenYongJia * @CreateTime: 2019-05-02 15:32 * @Email */ @Getter @Setter @AllArgsConstructor // 自动所有参数的构造方法方法 @NoArgsConstructor // 自动无参的构造方法方法 @Builder @Entity @Table(name = "jmccms_user") public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) @OrderBy @Column(columnDefinition = "bigint(19) unsigned COMMENT '用户id'") private Long userId; @Column(columnDefinition = "varchar(64) NOT NULL COMMENT '用户名称' ") private String userName; @Column(columnDefinition = "varchar(100) NOT NULL COMMENT '用户密码' ") private String userPassWord; @Column(columnDefinition = "datetime COMMENT '用户创建时间' ") @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss") //日期格式化为中国的时区 东8区 @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") //接受::字符串日期需要格式化为日期类型 private Date userCreateTime; @Column(columnDefinition = "datetime COMMENT '用户最后一次登录时间' ") @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss") //日期格式化为中国的时区 东8区 @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") //接受::字符串日期需要格式化为日期类型 private Date userLastLoginTime; @Column(columnDefinition = "timestamp COMMENT '最后一次修改时间'", nullable = false, updatable = false, insertable = false) @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss") //日期格式化为中国的时区 东8区 @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") //接受::字符串日期需要格式化为日期类型 private Timestamp userLastUpdateTime; @Column(columnDefinition = "varchar(64) NOT NULL COMMENT '创建人' ") private String userFounder; @Column(columnDefinition = "varchar(64) COMMENT '修改人' ") private String userUpdateMan; @JsonIgnore @ManyToMany(fetch = FetchType.EAGER) // 指定多对多关系 @Cascade(value = { CascadeType.ALL }) // 设置级联关系 @JoinTable(name = "jmccms_user_role", // 指定第三张中间表名称 joinColumns = { @JoinColumn(name = "user_id") }, // 本表主键userId与第三张中间表user_role_tb的外键user_role_tb_user_id对应 inverseJoinColumns = { @JoinColumn(name = "role_id") }) // 多对多关系另一张表与第三张中间表表的外键的对应关系 @NotFound(action = NotFoundAction.IGNORE) // NotFound : 意思是找不到引用的外键数据时忽略,NotFound默认是exception private Set<Role> rolesSet = new HashSet<>();// 用户所拥有的角色集合 }
- 建立数据库访问层
- 使用 Spring Data JPA 建立数据库十分简单,只需要定义一个继承了 JpaRepository 的接口,下面是博主项目的一个类,可以参照
package com.jmccms.dao; import com.jmccms.entity.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import javax.transaction.Transactional; import java.util.List; / * @Description: 用户接口 * @BelongsProject: Jmccms * @BelongsPackage: com.jmccms.dao * @Author: ChenYongJia * @CreateTime: 2019-05-02 18:05 * @Email */ public interface UserRepository extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> { / * 根据用户名和密码查询用户 * @return */ User findByUserNameAndUserPassWord(String userName, String userPassWord); / * 根据用户名查询用户 * @return */ User findByUserName(String userName); / * 根据用户id查询用户信息 * @param userId * @return */ User findByUserId(Long userId); / * 批量删除用户信息 * * @param userList * @return */ @Query(value = "DELETE FROM jmccms_user WHERE user_id IN (:userList)", nativeQuery = true) @Modifying @Transactional Integer deleteUser(@Param(value = "userList") List<String> userList); / * 根据ID查询用户角色 * * @param userId * @return */ @Query(value = "SELECT role_id FROM jmccms_user_role WHERE 1=1 AND user_id=:usersId ", nativeQuery = true) List<Long> getUserRole(@Param(value = "usersId") Long userId); }
- 继承了 JpaRepository 就相当于有了下面的数据访问操作方法,这些都是 Spring Data Jpa 封装好的。
欢迎大家来到IT世界,在知识的湖畔探索吧!// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.data.jpa.repository; import java.util.List; import org.springframework.data.domain.Example; import org.springframework.data.domain.Sort; import org.springframework.data.repository.NoRepositoryBean; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.QueryByExampleExecutor; @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); }
支持的关键字、示例及JPQL片段如下表所示:
|
Keyword |
Sample |
JPQL Snippet |
|
And |
findByLastnameAndFirstname |
… where x.lastname = ?1 and x.firstname = ?2 |
|
Or |
findByLastnameOrFirstname |
… where x.lastname = ?1 or x.firstname = ?2 |
|
Is,Equals |
indByFirstname,findByFirstnameIs,findByFirstnameEquals |
… where x.firstname = ?1 |
|
Between |
findByStartDateBetween |
… where x.startDate between ?1 and ?2 |
|
LessThan |
findByAgeLessThan |
… where x.age < ?1 |
|
LessThanEqual |
findByAgeLessThanEqual |
… where x.age <= ?1 |
|
GreaterThan |
findByAgeGreaterThan |
… where x.age > ?1 |
|
GreaterThanEqual |
findByAgeGreaterThanEqual |
… where x.age >= ?1 |
|
After |
findByStartDateAfter |
… where x.startDate > ?1 |
|
Before |
findByStartDateBefore |
… where x.startDate < ?1 |
|
IsNull |
findByAgeIsNull |
… where x.age is null |
|
IsNotNull,NotNull |
findByAge(Is)NotNull |
… where x.age not null |
|
Like |
findByFirstnameLike |
… where x.firstname like ?1 |
|
NotLike |
findByFirstnameNotLike |
… findByFirstnameNotLike |
|
StartingWith |
findByFirstnameStartingWith |
… where x.firstname like ?1 (parameter bound with appended %) |
|
EndingWith |
findByFirstnameEndingWith |
… where x.firstname like ?1 (parameter bound with prepended %) |
|
Containing |
findByFirstnameContaining |
… where x.firstname like ?1 (parameter bound wrapped in %) |
|
OrderBy |
findByAgeOrderByLastnameDesc |
… where x.age = ?1 order by x.lastname desc |
|
Not |
findByLastnameNot |
… where x.lastname <> ?1 |
|
In |
findByAgeIn(Collection ages) |
… where x.age in ?1 |
|
NotIn |
findByAgeNotIn(Collection ages) |
… where x.age not in ?1 |
|
True |
findByActiveTrue() |
… where x.active = true |
|
False |
findByActiveFalse() |
… where x.active = false |
|
IgnoreCase |
findByFirstnameIgnoreCase |
… where UPPER(x.firstame) = UPPER(?1) |
|
… |
… |
… |
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/127285.html