SpringBoot_JPA基礎
-
創建SpringBoot工程:springboot_jpa
-
生成項目的pom文件:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springboot_jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_jpa</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 添加lombok依賴
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
- 把application.properties改成application.yml,添加配置內容:
#數據庫連接
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&serverTimezone=GMT%2B8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
show-sql: true #在控制檯中打印sql
- 數據庫表employee表結構和內容:
表結構:
主鍵id自動遞增
表內容:
6. 數據庫表department表結構和內容:
表結構:
表內容:
7. Employee實體類
package com.example.demo.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Entity //告訴JPA這是一個要和數據庫表映射的實體類
@Table(name="employee") //用於指定和數據庫中的哪個表映射
public class Employee {
@Id //標識主鍵
@GeneratedValue(strategy = GenerationType.IDENTITY) //設置主鍵增長類型
private Integer id;
@Column(name = "last_name") //指定屬性和數據庫中的哪個字段映射
private String lastName;
@Column
private String email;
@Column
private Integer gender;
@Column(name = "d_id")
private Integer departmentId;
}
- EmployeeRepository接口(該接口內不需要寫任何方法)
package com.example.demo.repos;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.entity.Employee;
/**
* 自定義Repository,繼承JpaRepository
* 泛型1:要處理的實體類
* 泛型2:主鍵的類型
*
* @author BLU
*/
public interface EmployeeRepository extends JpaRepository<Employee, Integer>{
}
- 測試類SpringbootJpaApplicationTests
package com.example.demo;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.example.demo.entity.Employee;
import com.example.demo.repos.EmployeeRepository;
@SpringBootTest
class SpringbootJpaApplicationTests {
@Autowired
EmployeeRepository er;
@Test
public void test_findbyId() {
Optional<Employee> optional = er.findById(3);
System.out.println(optional);
}
}
- 運行test_findbyId(),控制檯打印:
Hibernate: select employee0_.id as id1_0_0_, employee0_.d_id as d_id2_0_0_, employee0_.email as email3_0_0_, employee0_.gender as gender4_0_0_, employee0_.last_name as last_nam5_0_0_ from employee employee0_ where employee0_.id=?
Optional[Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)]
- 保存單個數據
@Test
public void test_save1() {
Employee e = new Employee(null, "amy", "[email protected]", 2, 1);
er.save(e);
}
控制檯打印:
Hibernate: insert into employee (d_id, email, gender, last_name) values (?, ?, ?, ?)
數據庫增加了一條記錄:
- 保存多個數據
@Test
public void test_save2() {
Employee e1 = new Employee(null, "amy1", "[email protected]", 2, 1);
Employee e2 = new Employee(null, "amy2", "[email protected]", 2, 2);
Employee e3 = new Employee(null, "amy3", "[email protected]", 2, 3);
er.saveAll(Arrays.asList(e1,e2,e3));
}
控制檯打印:
Hibernate: insert into employee (d_id, email, gender, last_name) values (?, ?, ?, ?)
Hibernate: insert into employee (d_id, email, gender, last_name) values (?, ?, ?, ?)
Hibernate: insert into employee (d_id, email, gender, last_name) values (?, ?, ?, ?)
數據庫增加了3條記錄:
13. 修改數據
注:添加和修改調用的都是save方法,區別是添加方法傳入的id爲空,修改方法傳入的id爲要修改的記錄的id
@Test
public void test_modify() {
Employee e = new Employee(1, "zhangsan", "[email protected]", 2, 1);
er.save(e);
}
控制檯打印:
Hibernate: select employee0_.id as id1_0_0_, employee0_.d_id as d_id2_0_0_, employee0_.email as email3_0_0_, employee0_.gender as gender4_0_0_, employee0_.last_name as last_nam5_0_0_ from employee employee0_ where employee0_.id=?
Hibernate: update employee set d_id=?, email=?, gender=?, last_name=? where id=?
數據庫中的第一條記錄被修改了:
14. 刪除記錄
@Test
public void test_delete() {
er.deleteById(9);
}
控制檯打印:
Hibernate: select employee0_.id as id1_0_0_, employee0_.d_id as d_id2_0_0_, employee0_.email as email3_0_0_, employee0_.gender as gender4_0_0_, employee0_.last_name as last_nam5_0_0_ from employee employee0_ where employee0_.id=?
Hibernate: delete from employee where id=?
數據庫中的第9條記錄被刪除了
15. 查詢全部數據
@Test
public void test_findAll() {
List<Employee> list = er.findAll();
for(Employee e : list) {
System.out.println(e);
}
}
控制檯打印:
Hibernate: select employee0_.id as id1_0_, employee0_.d_id as d_id2_0_, employee0_.email as email3_0_, employee0_.gender as gender4_0_, employee0_.last_name as last_nam5_0_ from employee employee0_
Employee(id=1, lastName=zhangsan, [email protected], gender=2, departmentId=1)
Employee(id=2, lastName=lisi, [email protected], gender=1, departmentId=2)
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)
Employee(id=4, lastName=linda, email=linda.qq.com, gender=2, departmentId=2)
Employee(id=5, lastName=ruby, [email protected], gender=2, departmentId=3)
Employee(id=6, lastName=amy, [email protected], gender=2, departmentId=1)
Employee(id=7, lastName=amy1, [email protected], gender=2, departmentId=1)
Employee(id=8, lastName=amy2, [email protected], gender=2, departmentId=2)
- 查詢多個數據
@Test
public void test_findAllById() {
List<Employee> list = er.findAllById(Arrays.asList(2,3,4));
for(Employee e : list) {
System.out.println(e);
}
}
控制檯打印:
Hibernate: select employee0_.id as id1_0_, employee0_.d_id as d_id2_0_, employee0_.email as email3_0_, employee0_.gender as gender4_0_, employee0_.last_name as last_nam5_0_ from employee employee0_ where employee0_.id in (? , ? , ?)
Employee(id=2, lastName=lisi, [email protected], gender=1, departmentId=2)
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)
Employee(id=4, lastName=linda, email=linda.qq.com, gender=2, departmentId=2)
- 分頁查詢 (參數0表示第1頁,參數3表示每頁的記錄個數)
@Test
public void test_page() {
PageRequest pageRequest = PageRequest.of(0, 3);
Page<Employee> page = er.findAll(pageRequest);
System.out.println("totalpages"+page.getTotalPages());
List<Employee> list = page.getContent();
for(Employee e : list) {
System.out.println(e);
}
}
控制檯打印:
Hibernate: select employee0_.id as id1_0_, employee0_.d_id as d_id2_0_, employee0_.email as email3_0_, employee0_.gender as gender4_0_, employee0_.last_name as last_nam5_0_ from employee employee0_ limit ?
Hibernate: select count(employee0_.id) as col_0_0_ from employee employee0_
totalpages3
Employee(id=1, lastName=zhangsan, [email protected], gender=2, departmentId=1)
Employee(id=2, lastName=lisi, [email protected], gender=1, departmentId=2)
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)
- 排序查詢(按id和gender逆序排序)
注:這裏Order要導入的包爲:import org.springframework.data.domain.Sort.Order;
@Test
public void test_sort() {
Order o_id = new Order(Direction.DESC,"id");
Order o_gender = new Order(Direction.DESC,"gender");
Sort sort = Sort.by(o_id,o_gender);
List<Employee> list = er.findAll(sort);
for(Employee e : list) {
System.out.println(e);
}
}
控制檯打印:
Hibernate: select employee0_.id as id1_0_, employee0_.d_id as d_id2_0_, employee0_.email as email3_0_, employee0_.gender as gender4_0_, employee0_.last_name as last_nam5_0_ from employee employee0_ order by employee0_.id desc, employee0_.gender desc
Employee(id=8, lastName=amy2, [email protected], gender=2, departmentId=2)
Employee(id=7, lastName=amy1, [email protected], gender=2, departmentId=1)
Employee(id=6, lastName=amy, [email protected], gender=2, departmentId=1)
Employee(id=5, lastName=ruby, [email protected], gender=2, departmentId=3)
Employee(id=4, lastName=linda, email=linda.qq.com, gender=2, departmentId=2)
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)
Employee(id=2, lastName=lisi, [email protected], gender=1, departmentId=2)
Employee(id=1, lastName=zhangsan, [email protected], gender=2, departmentId=1)
- 自定義接口EmployeeDao繼承Repository
package com.example.demo.repos;
import org.springframework.data.repository.Repository;
import com.example.demo.entity.Employee;
/**
* 自定義Repository,繼承JpaRepository
* 泛型1:要處理的實體類
* 泛型2:主鍵的類型
*
* @author BLU
*/
public interface EmployeeDao extends Repository<Employee, Integer>{
}
- 在測試類中注入EmployeeDao
@Autowired
EmployeeDao eDao;
- 在EmployeeDao接口中添加方法:
//根據id查詢
Employee findById(Integer id);
//根據lastName查詢
Employee findByLastName(String uname);
//模糊查詢
List<Employee> findByLastNameLike(String lastName);
- findById(Integer id)測試方法:
@Test
public void test_eDao_findById() {
Employee e = eDao.findById(3);
System.out.println(e);
}
控制檯打印:
Hibernate: select employee0_.id as id1_0_0_, employee0_.d_id as d_id2_0_0_, employee0_.email as email3_0_0_, employee0_.gender as gender4_0_0_, employee0_.last_name as last_nam5_0_0_ from employee employee0_ where employee0_.id=?
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)
- findByLastName(String uname)方法:
@Test
public void test_eDao_findByLastName() {
Employee e = eDao.findByLastName("linda");
System.out.println(e);
}
控制檯打印:
Hibernate: select employee0_.id as id1_0_, employee0_.d_id as d_id2_0_, employee0_.email as email3_0_, employee0_.gender as gender4_0_, employee0_.last_name as last_nam5_0_ from employee employee0_ where employee0_.last_name=?
Employee(id=4, lastName=linda, email=linda.qq.com, gender=2, departmentId=2)
- findByLastNameLike(String lastName)方法:
@Test
public void test_eDao_findByLastNameLike() {
List<Employee> list = eDao.findByLastNameLike("%amy%");
for(Employee e : list) {
System.out.println(e);
}
}
控制檯打印:
Hibernate: select employee0_.id as id1_0_, employee0_.d_id as d_id2_0_, employee0_.email as email3_0_, employee0_.gender as gender4_0_, employee0_.last_name as last_nam5_0_ from employee employee0_ where employee0_.last_name like ? escape ?
Employee(id=6, lastName=amy, [email protected], gender=2, departmentId=1)
Employee(id=7, lastName=amy1, [email protected], gender=2, departmentId=1)
Employee(id=8, lastName=amy2, [email protected], gender=2, departmentId=2)
- 符合SpringData方法定義規範的寫法示例:
findByLastName
...where x.lastname = ?1
findByLastnameAndFirstname
...where x.lastname = ?1 and x.firstname = ?2
findByLastnameOrFirstname
...where x.lastname = ?1 or x.firstname = ?2
findByIdBetween
...where x.id between ?1 and ?2
findByAgeLessThan
...where x.age < ?1
findByAgeLessThanEqual
...where x.age <= ?1
findByAgeGreaterThan
...where x.age > ?1
findByAgeGreaterThanEqual
...where x.age >= ?1
findByAgeIsNull
...where x.age is null
findByAgeIsNotNull
...where x.age not null
findByLastNameLike
...where x.lastname like ?1
findByLastNameNotLike
...where x.lastname not like ?1
findByAgeOrderByLastnameDesc
...where x.age = ?1 order by x.lastname desc
findByLastNameNot
...where x.lastname <> ?1
findByAgeIn
...where x.age in ?1
findByAgeNotIn
...where x.age not in ?1
findByActiveTrue
...where x.active = true
findByActiveFalse
...where x.active = false
級聯查詢
在上面的查詢例子中查出的Employee的departmentId結果是部門id:
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=1)
而需求應該是:
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=Department(id=1, departmentName=銷售部))
- 添加Department實體類:
package com.example.demo.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
@Entity
@Table(name="department")
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column(name = "department_name")
private String departmentName;
}
- 修改Employee實體類的departmentId屬性:
將 @Column(name = “d_id”) 註解替換爲 @JoinColumn(name = “d_id”)
添加 @ManyToOne 註解
//@Column(name = "d_id")
@ManyToOne
@JoinColumn(name = "d_id")
private Department departmentId;
}
- EmployeeDao
package com.example.demo.repos;
import java.util.List;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.Repository;
import com.example.demo.entity.Employee;
public interface EmployeeDao extends Repository<Employee, Integer>{
//根據id查詢Employee,並級聯查詢Department
//兩表關聯,如果不指定,則默認根據id查詢的id是主表Employee的id
Employee findById(Integer id);
//根據Department的id查詢Employee
//departmentId是Employee實體裏的屬性,id是Department實體裏的屬性,中間用下劃線隔開
List<Employee> findBydepartmentId_id(Integer id);
//模糊查詢+查詢排序(只要把方法的最後一個參數設置爲Sort就可以實現查詢結果排序)
List<Employee> findByLastNameLike(String uname, Sort sort);
//模糊查詢+查詢分頁(只要把方法的最後一個參數設置爲Pageable就可以實現查詢結果分頁)
//注:Sort和Pageable都是org.springframework.data.domain包下的
List<Employee> findByLastNameLike(String uname, Pageable pageable);
}
- 編寫測試方法:
package com.example.demo;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import com.example.demo.entity.Employee;
import com.example.demo.repos.EmployeeDao;
@SpringBootTest
class SpringbootJpaApplicationTests {
@Autowired
EmployeeDao eDao;
@Test
public void test_eDao_findbyId() {
Employee employee = eDao.findById(3);
System.out.println(employee);
}
@Test
public void test_eDao_findBydepartmentId_id() {
List<Employee> list = eDao.findBydepartmentId_id(1);
for(Employee e : list) {
System.out.println(e);
}
}
@Test
public void testsort_eDao_findByLastNameLike() {
Sort sort = Sort.by(Direction.DESC, "id");
List<Employee> list = eDao.findByLastNameLike("%amy%", sort);
for(Employee e : list) {
System.out.println(e);
}
}
@Test
public void testpageable_eDao_findByLastNameLike() {
//參數0表示第1頁,參數2表示每頁兩條記錄
PageRequest pageRequest = PageRequest.of(0, 2);
List<Employee> list = eDao.findByLastNameLike("%amy%", pageRequest);
for(Employee e : list) {
System.out.println(e);
}
}
}
test_eDao_findbyId() 運行結果:
Hibernate: select employee0_.id as id1_1_0_, employee0_.d_id as d_id5_1_0_, employee0_.email as email2_1_0_, employee0_.gender as gender3_1_0_, employee0_.last_name as last_nam4_1_0_, department1_.id as id1_0_1_, department1_.department_name as departme2_0_1_ from employee employee0_ left outer join department department1_ on employee0_.d_id=department1_.id where employee0_.id=?
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=Department(id=1, departmentName=銷售部))
test_eDao_findBydepartmentId_id() 運行結果:
Hibernate: select employee0_.id as id1_1_, employee0_.d_id as d_id5_1_, employee0_.email as email2_1_, employee0_.gender as gender3_1_, employee0_.last_name as last_nam4_1_ from employee employee0_ left outer join department department1_ on employee0_.d_id=department1_.id where department1_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Employee(id=1, lastName=zhangsan, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=Department(id=1, departmentName=銷售部))
Employee(id=6, lastName=amy, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))
Employee(id=7, lastName=amy1, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))
testsort_eDao_findByLastNameLike() 運行結果:
Hibernate: select employee0_.id as id1_1_, employee0_.d_id as d_id5_1_, employee0_.email as email2_1_, employee0_.gender as gender3_1_, employee0_.last_name as last_nam4_1_ from employee employee0_ where employee0_.last_name like ? escape ? order by employee0_.id desc
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Employee(id=8, lastName=amy2, [email protected], gender=2, departmentId=Department(id=2, departmentName=運營部))
Employee(id=7, lastName=amy1, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))
Employee(id=6, lastName=amy, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))
testpageable_eDao_findByLastNameLike 運行結果:
Hibernate: select employee0_.id as id1_1_, employee0_.d_id as d_id5_1_, employee0_.email as email2_1_, employee0_.gender as gender3_1_, employee0_.last_name as last_nam4_1_ from employee employee0_ where employee0_.last_name like ? escape ? limit ?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Employee(id=6, lastName=amy, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))
Employee(id=7, lastName=amy1, [email protected], gender=2, departmentId=Department(id=1, departmentName=銷售部))
單個排序規則寫法:
Sort sort = Sort.by(Direction.DESC, "id");
List<Employee> list = eDao.findByLastNameLike("%amy%", sort);
SQL語句:
order by employee0_.id desc
多個排序規則寫法:
Order oid = new Order(Direction.DESC, "id");
Order ogender = new Order(Direction.ASC, "gender");
Sort sort = Sort.by(oid , ogender);
List<Employee> list = eDao.findByLastNameLike("%amy%", sort);
SQL語句:
order by employee0_.id desc, employee0_.gender asc
分頁中添加排序規則的寫法:
Sort sort = Sort.by(Direction.DESC, "id");
PageRequest pageRequest = PageRequest.of(0, 2, sort);
List<Employee> list = eDao.findByLastNameLike("%amy%", pageRequest);
註解
@RepositoryDefinition
在定義Dao接口時,需要繼承Repository接口,示例如下:
public interface EmployeeDao extends Repository<Employee, Integer>{
}
可以使用 @RepositoryDefinition 註解代替上面的寫法,示例如下:
@RepositoryDefinition(domainClass=Employee.class, idClass=Integer.class)
public interface EmployeeDao{
}
@Query執行JPQL
在定義Dao接口方法時,方法名需要符合SpringData方法定義規範
使用@Query可以使方法命名擺脫JPA的規範約束,示例:
根據性別查詢Employee的Dao接口方法:
//@Query中寫的是JPQL語句,不是SQL語句
//Employee是實體類名,不是數據表名。gender是Employee實體的屬性
//佔位符 ?1 表示的是方法中的第一個參數
@Query("select e from Employee e where gender= ?1")
List<Employee> chaxunGender(Integer gender);
根據性別查詢Employee的測試方法:
@Test
public void test_eDao_chaxunGender() {
List<Employee> list = eDao.chaxunGender(1);
for(Employee e : list) {
System.out.println(e);
}
}
結果:
Hibernate: select employee0_.id as id1_1_, employee0_.d_id as d_id5_1_, employee0_.email as email2_1_, employee0_.gender as gender3_1_, employee0_.last_name as last_nam4_1_ from employee employee0_ where employee0_.gender=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Employee(id=2, lastName=lisi, [email protected], gender=1, departmentId=Department(id=2, departmentName=運營部))
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=Department(id=1, departmentName=銷售部))
@Param
在上例使用@Query中自定義JPQL語句中,指定參數的方式是佔位符?1
也可以通過@Param註解指定參數的名稱。示例如下:
@Query("select e from Employee e where gender= :gender")
List<Employee> chaxunGender(@Param("gender")Integer gender);
@Query執行原生SQL
示例1:
Dao接口查詢方法:
//使用原生sql(設置nativeQuery=true)
@Query(value="select * from employee where gender = ?1", nativeQuery=true)
List<Employee> chaxunGender(Integer gender);
測試方法:
@Test
public void test_eDao_chaxunGender() {
List<Employee> list = eDao.chaxunGender(1);
for(Employee e : list) {
System.out.println(e);
}
}
結果:
Hibernate: select * from employee where gender = ?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Employee(id=2, lastName=lisi, [email protected], gender=1, departmentId=Department(id=2, departmentName=運營部))
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=Department(id=1, departmentName=銷售部))
@Modifying註解實現修改或刪除
@Transactional事務註解保證正常執行(javax.transaction.Transactional)
修改示例:
Dao接口修改方法:
@Transactional
@Modifying
@Query("update Employee e set email = ?1 where id = ?2")
public void modifyById(String email, Integer id);
測試方法:
@Test
public void test_eDao_ModifyById() {
eDao.modifyById("[email protected]", 1);
}
控制檯打印:
Hibernate: update employee set email=? where id=?
原數據:
運行後:
刪除示例:
Dao接口刪除方法:
@Transactional
@Modifying
@Query("delete from Employee where id = ?1")
public void deleteById(Integer id);
測試方法:
@Test
public void test_eDao_deleteById() {
eDao.deleteById(9);
}
控制檯打印:
Hibernate: delete from employee where id=?
原數據:
執行測試後,第9條數據被刪除:
@NamedQuery註解實現單個命名查詢(javax.persistence.NamedQuery)
示例:
在Employee實體類上添加@NamedQuery註解(name指定方法名,query指定JPQL語句):
@NamedQuery(name = "Employee.findEmpByID",query = "select e from Employee e where id = ?1")
在EmployeeDao接口中聲明該方法,不需要寫任何註解。
public Employee findEmpByID(Integer id);
測試方法:
@Test
public void test_eDao_findEmpByID() {
Employee employee = eDao.findEmpByID(3);
System.out.println(employee);
}
運行結果:
Hibernate: select employee0_.id as id1_1_, employee0_.d_id as d_id5_1_, employee0_.email as email2_1_, employee0_.gender as gender3_1_, employee0_.last_name as last_nam4_1_ from employee employee0_ where employee0_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Employee(id=3, lastName=BLU, [email protected], gender=1, departmentId=Department(id=1, departmentName=銷售部))
@NamedQueries註解定義多個命名查詢的寫法:
@NamedQueries({
@NamedQuery(name = "",query = ""),
@NamedQuery(name = "",query = ""),
@NamedQuery(name = "",query = ""),
@NamedQuery(name = "",query = "")
})
@DynamicInsert
@DynamicUpdate
- Employee實體類加註解
@DynamicInsert(value = false)
@DynamicUpdate(value = false)
- 創建EmpCrudRep接口繼承CrudRepository
package com.example.demo.repos;
import org.springframework.data.repository.CrudRepository;
import com.example.demo.entity.Employee;
public interface EmpCrudRep extends CrudRepository<Employee, Integer>{
}
- 測試方法 (save方法的id爲空即表示添加方法)
@Test
public void test_empCrudRep() {
Department dept = new Department();
dept.setId(1);
Employee e = new Employee(null,"jack","[email protected]",null,dept);
empCrudRep.save(e);
}
- 運行結果:
Hibernate: insert into employee (d_id, email, gender, last_name) values (?, ?, ?, ?)
- 將註解@DynamicInsert的值改爲true
@DynamicInsert(value = true)
@DynamicUpdate(value = false)
- 運行測試方法
@Test
public void test_empCrudRep() {
Department dept = new Department();
dept.setId(1);
Employee e = new Employee(null,"jack1","[email protected]",null,dept);
empCrudRep.save(e);
}
- 運行結果 (在執行insert時,只有有值的字段纔會執行insert操作,值爲null的字段不執行insert操作):
Hibernate: insert into employee (d_id, email, last_name) values (?, ?, ?)
- 數據:
- 修改測試方法:
@Test
public void test_empCrudRep() {
Optional<Employee> optional = empCrudRep.findById(17);
Employee employee = optional.get();
employee.setGender(2);
empCrudRep.save(employee);
}
- sql打印:
Hibernate: select employee0_.id as id1_1_0_, employee0_.d_id as d_id5_1_0_, employee0_.email as email2_1_0_, employee0_.gender as gender3_1_0_, employee0_.last_name as last_nam4_1_0_, department1_.id as id1_0_1_, department1_.department_name as departme2_0_1_ from employee employee0_ left outer join department department1_ on employee0_.d_id=department1_.id where employee0_.id=?
Hibernate: select employee0_.id as id1_1_0_, employee0_.d_id as d_id5_1_0_, employee0_.email as email2_1_0_, employee0_.gender as gender3_1_0_, employee0_.last_name as last_nam4_1_0_ from employee employee0_ where employee0_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Hibernate: update employee set d_id=?, email=?, gender=?, last_name=? where id=?
- 將註解@DynamicUpdate的值改爲true
@DynamicInsert(value = true)
@DynamicUpdate(value = true)
- 測試方法:
@Test
public void test_empCrudRep() {
Optional<Employee> optional = empCrudRep.findById(18);
Employee employee = optional.get();
employee.setGender(2);
empCrudRep.save(employee);
}
- sql打印(只有set的值才進行了update操作,未修改的字段不進行操作)
Hibernate: select employee0_.id as id1_1_0_, employee0_.d_id as d_id5_1_0_, employee0_.email as email2_1_0_, employee0_.gender as gender3_1_0_, employee0_.last_name as last_nam4_1_0_, department1_.id as id1_0_1_, department1_.department_name as departme2_0_1_ from employee employee0_ left outer join department department1_ on employee0_.d_id=department1_.id where employee0_.id=?
Hibernate: select employee0_.id as id1_1_0_, employee0_.d_id as d_id5_1_0_, employee0_.email as email2_1_0_, employee0_.gender as gender3_1_0_, employee0_.last_name as last_nam4_1_0_ from employee employee0_ where employee0_.id=?
Hibernate: select department0_.id as id1_0_0_, department0_.department_name as departme2_0_0_ from department department0_ where department0_.id=?
Hibernate: update employee set gender=? where id=?
- 數據