Spring Data JPA的基礎概念及初步上手

一、JPA

1、定義

JPA是Java Persistence API的簡稱,中文名稱爲Java持久層API;主要包括以下內容:

(1)一套API標準:在javax.persistence的包下面,用來操作實體對象,執行CRUD操作,讓開發者從煩瑣的JDBC和SQL代碼中解脫出來。
(2)面向對象的查詢語言:Java Persistence Query Language(JPQL)。通過面向 對象而非面向數據庫的查詢語言查詢數據,避免程序的SQL語句緊密耦合。
(3)ORM(object/relational metadata)元數據的映射:JPA支持XML和JDK5.0註解兩種元數據的形式,元數據描述對象和表之間 的映射關係,框架據此將實體對象持久化到數據庫表中。

2、發展

JPA的宗旨是爲POJO提供持久化標準規範,經過這幾年的實踐探索,方便開發和測試的理念已經深入人心了。Hibernate 3.2+、TopLink 10.1.3以及OpenJPA都提供了JPA的實現。目前國外的互聯網公司已經大量使用了JPA的開發標準規範。
在這裏插入圖片描述

二、Spring Data JPA

1、介紹

可以理解爲JPA規範的再次封裝抽象,底層還是使用了Hibernate的JPA技術實現,引用JPQL(Java Persistence Query Language)查詢語言,屬於Spring整個生態體系的一部分。隨着Spring Boot和Spring Cloud在市場上的流行,Spring Data JPA也逐漸進入大家的視野,它們組成有機的整體,使用起來比較方便,加快了開發的效率,使開發者不需要關心和配置更多的東西,完全可以沉浸在Spring的完整生態標準實現下。JPA上手簡單,開發效率高,對對象的支持比較好,又有很大的靈活性,市場的認可度越來越高。

2、Spring Data JPA是Spirng Data的子項目

Spring Data Commons
Spring Data Gemfire
Spring Data JPA
Spring Data KeyValue
Spring Data LDAP
Spring Data MongoDB
Spring Data REST
Spring Data Redis
Spring Data for Apache Cassandra
Spring Data for Apache Solr

3、Spring Data JPA的主要類及結構圖

七個Repository接口:

  1. Repository (org.springframework.data.repository)
  2. CrudRepository (org.springframework.data.repository)
  3. PagingAndSortingRepository (org.springframework.data.repository)
  4. QueryByExampleExecutor (org.springframework.data.repository.query)
  5. JpaRepository (org.springframework.data.jpa.repository)
  6. JpaSpecificationExecutor (org.springframework.data.jpa.repository)
  7. QueryDslPredicateExecutor (org.springframework.data.querydsl)

兩個實現類:

  • SimpleJpaRepository(org.springframework.data.jpa.repository.support)
  • QueryDslJpaRepository(org.springframework.data.jpa.repository.support)

類結構圖:
在這裏插入圖片描述

三、初步上手:Spring Boot 項目集成Spring Data JPA

1、環境
  • Spring Boot 2.x
  • JDK 1.8
  • Maven 3.0+
  • IntelliJ IDE 2019
  • Mysql5
  • druid1.1
  • log4jdbc1.16
<!--集中管理依賴版本-->
    <properties>
        <!-- JDK版本號 -->
        <java.version>1.8</java.version>
        <!-- druid版本號 -->
        <druid.version>1.1.10</druid.version>
        <!-- log4jdbc版本號 -->
        <log4jdbc.version>1.16</log4jdbc.version>
        <!-- common-pool2版本號 -->
        <commons-pool2.version>2.5.0</commons-pool2.version>
        <!--fastjson版本號-->
        <fastjson.version>1.2.58</fastjson.version>
        <!--mysql版本號-->
        <mysql.version>5.1.47</mysql.version>
        <!--swagger版本號-->
        <swagger.version>2.9.2</swagger.version>
    </properties>

    <!-- 項目繼承Spring Boot -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
    </parent>
 <!-- 引入外部依賴 -->
    <dependencies>
    	...
        <!--JPA-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        ...
    </dependencies>
2、數據庫建表
CREATE TABLE `user`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `open_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `gender` int(11) NULL DEFAULT NULL COMMENT '0-未知 1-male 2-female',
  `avatar_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `union_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `country` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `province` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `city` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `language` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `remarks` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `enabled` int(11) NULL DEFAULT 1 COMMENT '1-激活 0-禁用',
  `last_password_reset_time` datetime(0) NULL DEFAULT NULL,
  `create_time` datetime(0) NULL DEFAULT NULL,
  `update_time` datetime(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `open_id`(`open_id`) USING BTREE,
  UNIQUE INDEX `user_name`(`user_name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
3、Spring配置文件
#配置數據源
spring:
  datasource:
    druid:
      db-type: com.alibaba.druid.pool.DruidDataSource
      driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
      url: jdbc:log4jdbc:mysql://localhost:3306/startup?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
      username: root
      password: root

      # 初始化配置
      initial-size: 3
      # 最小連接數
      min-idle: 3
      # 最大連接數
      max-active: 15
      # 獲取連接超時時間
      max-wait: 5000
      # 連接有效性檢測時間
      time-between-eviction-runs-millis: 90000
      # 最大空閒時間
      min-evictable-idle-time-millis: 1800000
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false

      validation-query: select 1
      # 配置監控統計攔截的filters
      filters: stat
      stat-view-servlet:
        url-pattern: /druid/*
        reset-enable: false

      web-stat-filter:
        url-pattern: /*
        exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"

#配置 Jpa
  jpa:
    hibernate:
      # 生產環境設置成 none,避免程序運行時自動更新數據庫結構
      ddl-auto: none
4、創建實體類
/**
 * 用戶表
 *
 * @author zhuhuix
 * @date 2020-04-03
 */
@ApiModel(value = "用戶信息")
@Entity
@Getter
@Setter
@Table(name = "user")
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @NotNull(groups = Update.class)
    private Long id;


    @Column(name = "user_name", unique = true)
    private String userName;

    @JsonIgnore
    private String password;

    /**
     * 微信openId
     */
    @Column(unique = true, name = "open_id")
    private String openId;

    /**
     * 用戶暱稱
     */
    @Column(name="nick_name")
    private String nickName;

    /**
     * 性別 0-未知 1-male,2-female
     */
    private Integer gender;

    /**
     * 頭像地址
     */
    @Column(name = "avatar_url")
    private String avatarUrl;

    @Column(name = "union_id")
    private String unionId;

    private String country;

    private String province;

    private String city;

    private String language;

    @Email
    private String email;

    private String phone;

    private String remarks;

    private Boolean enabled;

    @JsonIgnore
    @Column(name = "last_password_reset_time")
    private Timestamp lastPasswordResetTime;

    @JsonIgnore
    @Column(name = "create_time")
    @CreationTimestamp
    private Timestamp createTime;

    @JsonIgnore
    @Column(name = "update_time")
    @UpdateTimestamp
    private Timestamp updateTime;

}
4、創建Spring Data JPA倉庫類(DAO接口)
/**
 * 用戶DAO接口層
 * @author zhuhuix
 * @date 2020-04-03
 */
public interface UserRepository extends JpaRepository<User,Long>, JpaSpecificationExecutor<User> {
	//該接口繼承JpaRepository及JpaSpecificationExecutor接口,
	//該接口中已包含默認基本的CRUD成員方法,比如:
	//findById,create,delete,update等
}
5、創建服務接口及服務接口實現類調用DAO接口
/**
 * 用戶接口實現類
 *
 * @author zhuhuix
 * @date 2020-04-03
 */
@Slf4j
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;

    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<User> create(User user) {
        return new Result<User>().ok(userRepository.save(user));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(User user) {
        userRepository.delete(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<User> update(User user) {
        return new Result<User>().ok(userRepository.save(user));
    }

    @Override
    public Result<User> findById(Long id) {
        Optional<User> optional = userRepository.findById(id);
        return optional.map(user -> new Result<User>().ok(user)).orElse(null);
    }

    @Override
    public Result<User> findByOpenId(String openId) {
        return new Result<User>().ok(userRepository.findByOpenId(openId));
    }
}
6、編寫測試類進行測試
@SpringBootTest
@Slf4j
public class UserJPATest {
    @Test
    void test() {
        UserService userService = SpringContextHolder.getBean(UserService.class);
        userService.findById(1L);
    }
}

測試圖片

四、總結

Spring Data JPA非常強大,且容易上手:在DAO層只需繼承默認接口,無需手寫SQL語句。測試類進行測試時,Spring Data JPA會根據DAO調用方法,自動生成SQL語句,進行表數據的增刪改查。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章