網上看到的,記錄一下,原文:https://blog.csdn.net/Lee_Ho_/article/details/81014215java
一:引言
對於傳統關係型數據庫,Spring Boot使用JPA(Java Persistence API)資源庫來實現對數據庫的操做,簡單來講,JPA就是爲POJO(Plain Ordinary Java Object)提供持久化的標準規範,即將Java普通對象經過對象關係映射(Object Relational Mapping,ORM)持久化到數據庫中。mysql
二:使用方式
2.1:JPA配置
爲了使用JPA和MySQL,建立Spring Boot的Maven工程,在POM文件當中引入以下依賴:web
<?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.example</groupId>
<artifactId>spring-boot-jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-boot-jpa</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.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>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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>
</dependency>
</dependencies>
<build>
<finalName>jpa</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>
repackage
</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
application.yml配置:spring
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?characterEncoding=utf8
username: root
password: cuoai1995
jpa:
database: mysql
show-sql: true
#Hibernate ddl auto (validate|create|create-drop|update)
hibernate:
ddl-auto: update
naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialectsql
2.2:實體建模:
爲了演示JPA的使用方式,創建適當的實體關係,並演示如何經過註解方式實現實體建模:數據庫
實體之間的關係以下圖所示:apache
根據圖上關係進行實體建模:springboot
部門類:session
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name = "department")
public class Department implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
角色類:app
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Table(name = "role")
public class Role implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
用戶類(getter and setter...):
import com.fasterxml.jackson.annotation.JsonBackReference;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
@Entity
@Table(name = "user")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createDate;
@ManyToOne
@JoinColumn(name = "did")
@JsonBackReference
private Department department;
@ManyToMany(cascade = {}, fetch = FetchType.EAGER)
@JoinTable(name = "user_role", joinColumns = {@JoinColumn(name = "user_id")},
inverseJoinColumns = {@JoinColumn(name = "roles_id")})
private List<Role> roles;
這裏使用了一張新表user_role來表示用戶表和角色表多對多的依賴關係。
2.3:Spring Boot配置JPA測試環境:
建立JPA的配置類:JpaConfiguration,相關說明見配置類註釋:
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Order(Ordered.HIGHEST_PRECEDENCE)//定義組件的加載順序,這裏爲最高級
@Configuration//代表這是一個配置類
@EnableTransactionManagement(proxyTargetClass = true)//啓用JPA的事物管理
@EnableJpaRepositories(basePackages = "com.example.springbootjpa.repository")//啓動JPA資源庫並設置接口資源庫的位置
@EntityScan(basePackages = "com.example.springbootjpa.pojo")//實體類位置
public class JpaConfiguration {
/**
* @Description: 這裏說明爲何要聲明一個PersistenceExceptionTranslationPostProcessor 的Bean對象,引用Spring官方文檔的一句話:
* (1)scanned by Spring component-scanning
* (2)catch platformspecific exceptions and rethrow them as one of Spring’s unified unchecked exceptions
But if you’re using Hibernate contextual sessions and not a Hibernate template,how can the exception
translation take place?
翻譯過來就是:@Repository有兩做用:
(1):用於被容器掃描:
(2):捕獲平臺特定的異常並將它們從新拋出,做爲Spring的一個未檢查的異常。(用於事務的管理,例如捕獲異常回滾)
可是,若是您使用的是Hibernate contextual sessions上下文會話而不是Hibernate template,那麼異常轉換是如何發生的呢?
那麼,這就是配置這個類的做用。
* @return
*/
@Bean
PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor(){
return new PersistenceExceptionTranslationPostProcessor();
}
}
三:建立實體對應的Jpa接口
用戶接口:
import com.example.springbootjpa.pojo.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByName(String name);
}
部門接口:
import com.example.springbootjpa.pojo.Department;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface DepartmentRepository extends JpaRepository<Department, Long> {
}
角色接口:
import com.example.springbootjpa.pojo.Role;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
}
四:測試
在作完如上工做以後,就能夠進行下一步測試了。
import com.example.springbootjpa.pojo.Department;
import com.example.springbootjpa.pojo.Role;
import com.example.springbootjpa.pojo.User;
import com.example.springbootjpa.repository.DepartmentRepository;
import com.example.springbootjpa.repository.RoleRepository;
import com.example.springbootjpa.repository.UserRepository;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Date;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MysqlTest {
private static Logger logger = LoggerFactory.getLogger(MysqlTest.class);
@Autowired
private UserRepository userRepository;
@Autowired
private DepartmentRepository departmentRepository;
@Autowired
private RoleRepository roleRepository;
@Before
public void initData(){
userRepository.deleteAll();
roleRepository.deleteAll();
departmentRepository.deleteAll();
Department department = new Department();
department.setName("開發部");
departmentRepository.save(department);
Assert.assertNotNull(department.getId());
Role role = new Role();
role.setName("admin");
roleRepository.save(role);
Assert.assertNotNull(role.getId());
User user = new User();
user.setName("user");
user.setCreateDate(new Date());
user.setDepartment(department);
List<Role> roles = roleRepository.findAll();
Assert.assertNotNull(roles);
user.setRoles(roles);
userRepository.save(user);
Assert.assertNotNull(user.getId());
}
@Test
public void findPage(){
Pageable pageable = PageRequest.of(0, 10, new Sort(Sort.Direction.ASC, "id"));
Page<User> page = userRepository.findAll(pageable);
Assert.assertNotNull(page);
for (User user : page.getContent()){
logger.info("====user==== user name:{}, department name:{}, role name:{}", user.getName(),
user.getDepartment().getName(), user.getRoles().get(0).getName());
}
}
@Test
public void testFindByName(){
String name = "user";
User user = userRepository.findByName(name);
Assert.assertNotNull(user);
logger.info(user.getName());
}
}
結果:
六:總結
一:爲何要繼承JpaRepository?
以UserRepository爲例,來看看整個的繼承體系:
可見,Jpa資源庫已經給咱們提供了豐富的方法來知足普通的操做需求。
二:自定義方法的實現:
Jpa自己還提供了一些自定義聲明方法的規則,例如:在接口中使用關鍵字findBy、readBy、getBy做爲方法名的前綴,拼接實體類中的屬性字段(首字母大寫),並可選擇拼接一些SQL關鍵字來組合成一個查詢方法,例如,對於用戶實體,關鍵字能夠這樣使用:
1.And,如:findByIdAndName(Long id, String name);
2.Or,如:findByIdOrName(Long id, String name);
3.Between,如:findByCreateDateBetween(Date start, Date end);
4.LessThan,如:findByCreateDateLessThan(Date start);
5.GreaterThan,如:findByCreateDateGreaterThan(Date start);
6.IsNull,如:findByNameIsNull();
7.IsNotNull,與上等價
8.Like,如:findByNameLike(String name);
9.NotLike:與上等價
10.OrderBy,如:findByNameOrderByIdAsc(String name);
11.Not,如:findByNameNot(String name);
12.In,如:findByNameIn(Collection<String> nameList);
13.NotIn,與上等價。
加入說上面這些仍是不可以知足你的業務需求,你一樣能夠寫一個自定義的方法,使用@Query註解+HQL語句實現你想要的效果。--------------------- 版權聲明:本文爲CSDN博主「籠中人.」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處連接及本聲明。原文連接:https://blog.csdn.net/Lee_Ho_/article/details/81014215