//本文作者:cuifuan
什么是JPA?
一種規范,並非ORM框架,也就是ORM上統一的規范
用了之后可以做什么,為什么要用?
代碼解釋:
實體類
package com.example.springredis.entity; import lombok.Data; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import java.io.Serializable; @Entity @Data public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private String account; private String pwd; }
dao層
@Repository public interface UserDao extends JpaRepository<User, Long> { }
測試類
@Autowired private UserDao userDao; public void findAllTest() { System.out.println(userDao.findAll().toString()); }
上面的操作已經完成了一個查詢全部,相信不用在做多余的解釋了
JPA優點:主要就是簡單易用,集成方便,可以不用寫SQL語句
准備工作
這里的環境
- JDK 1.8 以上
- IDEA 2018.2
- Gradle 4+ 或者 Maven 3.2+
- 在https://start.spring.io/ 初始化一個項目
這里使用的是Gradle
下載之后請在IDEA導入項目
build.gradle配置
buildscript { ext { springBootVersion = '2.1.0.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'java-library' apply plugin: 'idea' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = 1.8 repositories { maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } } //Gradle3.4新增了Java-library插件,java-library插件使用了新的依賴配置implementation和api。舊的依賴配置compile被廢棄 dependencies { implementation('org.springframework.boot:spring-boot-starter-data-jpa') implementation('mysql:mysql-connector-java') compileOnly('org.projectlombok:lombok') testImplementation('org.springframework.boot:spring-boot-starter-test') }
開始定義一個簡單的實體
package com.example.springbootjpademo.entity; import lombok.Data; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity @Data public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String ename; protected User() { } public User(String name, String ename) { this.name = name; this.ename = ename; } @Override public String toString() { /* JAVA字符串格式化-String.format() %s 字符串類型 %d 整數類型(十進制) */ return String.format("Customer[id=%d, name='%s', ename='%s']", id, name, ename); } }
- 這里有一個User類,它有三個屬性,id,name和ename。你還有兩個構造函數。默認構造函數僅為JPA而存在。您不會直接使用它,因此它被指定為 protected 。另一個構造函數是您將用於創建要保存到數據庫的user實例的構造函數。
- 在User類上加 @Entity 注解,表示這個是一個 JPA 的實體,如果在 User 類上沒有加 @Table 注解,表明該實體將映射到名為user的表,如果要加上 @Table ,可以在其 name 屬性里寫入表名,如: @Table(name = "t_user")
- User的id屬性使用@Id注釋,以便JPA將其識別為對象的ID。id屬性也使用@GeneratedValue注釋
- @GeneratedValue(strategy = GenerationType.IDENTITY) 自增長ID策略
- 其他兩個屬性name和ename未注釋。表明它們將映射到與屬性本身相同一名稱的列,比如,User實體中的name屬性映射user表中的name列。
- toString() 方便將打印出實體的屬性
創建一個 UserRepository 接口
這里很簡單,直接繼承核心接口JpaRepository
src/main/java/com/example/springbootjpademo/repository/UserRepository.java
package com.example.springbootjpademo.repository; import com.example.springbootjpademo.entity.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface UserRepository extends JpaRepository<User, Long> { }
配置文件application.yml
修改application.properties 為 application.yml
src/main/resources/application.yml
spring: # 數據源配置 datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8&useSSL=false username: root password: 123456 jpa: # 在 SrpingBoot 2.0 版本中,Hibernate 創建數據表的時候,默認的數據庫存儲引擎選擇的是 MyISAM #(之前好像是 InnoDB,這點比較詭異)。這個參數是在建表的時候,將默認的存儲引擎切換為 InnoDB 用的。 database-platform: org.hibernate.dialect.MySQL5InnoDBDialect # spring.jpa.show-sql=true 配置在日志中打印出執行的 SQL 語句信息。 show-sql: true # 配置指明在程序啟動的時候要刪除並且創建實體類對應的表。 # create 這個參數很危險,因為他會把對應的表刪除掉然后重建。所以千萬不要在生成環境中使用。只有在測試環境中,一開始初始化數據庫結構的時候才能使用一次。 # ddl-auto:create----每次運行該程序,沒有表格會新建表格,表內有數據會清空 # ddl-auto:create-drop----每次程序結束的時候會清空表 # ddl-auto:update----每次運行程序,沒有表格會新建表格,表內有數據不會清空,只會更新(推薦) # ddl-auto:validate----運行程序會校驗數據與數據庫的字段類型是否相同,不同會報錯 hibernate.ddl-auto: update
建立測試類進行查詢
src/test/java/com/example/springbootjpademo/SpringbootJpaDemoApplicationTests.java
package com.example.springbootjpademo; import com.example.springbootjpademo.repository.UserRepository; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SpringbootJpaDemoApplicationTests { @Autowired private UserRepository userRepository; @Test public void contextLoads() { System.out.println(userRepository.findAll().toString()); } }
輸出
注意
如果出現下列等錯誤:
Error:(41, 13) java: 找不到符號
符號: 方法 setName(java.lang.String)
位置: 類型為com.example.springbootjpademo.entity.User的變量 user
請注意下面的設置是否正確:
其他操作
src/test/java/com/example/springbootjpademo/SpringbootJpaDemoApplicationTests.java
package com.example.springbootjpademo; import com.example.springbootjpademo.entity.User; import com.example.springbootjpademo.repository.UserRepository; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SpringbootJpaDemoApplicationTests { @Autowired private UserRepository userRepository; @Test public void contextLoads() { System.out.println(userRepository.findAll().toString()); } @Before public void add() { userRepository.save(new User("英雄聯盟", "lol")); } //修改操作 @After public void update() { // ifPresent 如果存在值,則使用值調用指定的使用者,否則不執行任何操作。 userRepository.findById(1L).ifPresent(user -> { user.setName("xiugaihou"); userRepository.save(user); System.out.println(user.toString()); }); } //刪除 @After public void del() { userRepository.findById(2L).ifPresent(user -> userRepository.delete(user)); } }
最后數據庫的值: