网上看到的,记录一下,原文:https://blog.csdn.net/Lee_Ho_/article/details/81014215
一:引言 对于传统关系型数据库,Spring Boot使用JPA(Java Persistence API)资源库来实现对数据库的操作,简单来说,JPA就是为POJO(Plain Ordinary Java Object)提供持久化的标准规范,即将Java普通对象通过对象关系映射(Object Relational Mapping,ORM)持久化到数据库中。
二:使用方式2.1:JPA配置 为了使用JPA和MySQL,创建Spring Boot的Maven工程,在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 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: 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.MySQL5Dialect
2.2:实体建模: 为了演示JPA的使用方式,建立适当的实体关系,并演示如何通过注解方式实现实体建模:
实体之间的关系如下图所示:
根据图上关系进行实体建模:
部门类:
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; }}角色类:
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;@Repositorypublic 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;@Repositorypublic interface DepartmentRepository extends JpaRepository<Department, Long> {}角色接口:
import com.example.springbootjpa.pojo.Role;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.stereotype.Repository;@Repositorypublic 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)@SpringBootTestpublic 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语句实现你想要的效果。--------------------- 版权声明:本文为博主「笼中人.」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/Lee_Ho_/article/details/81014215
转载于:https://www.cnblogs.com/linwenbin/p/11357368.html
相关资源:spring-boot-starter-data-jpa 的二级缓存