Spring Boot JPA
前言
JPA
的全称是 Java Persistence API
, 即 Java 持久化API
,是 SUN 公司推出的一套基于ORM
的规范,内部是由一系列的接口和抽象类构成。JPA
通过JDK 5.0
注解描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
Spring Boot Jpa
是 Spring 基于 ORM
框架、Jpa
规范的基础上封装的一套Jpa
应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。
一、概述
JPA
特性:
- 标准化
JPA 是 JCP 组织发布的 Java EE 标准之一
- 容器级特性的支持
JPA 框架中支持大数据集、事务、并发等容器级事务
- 简单方便
JPA 的主要目标之一就是提供更加简单的编程模型
- 查询能力
JPA 的查询语言是面向对象而非面向数据库
- 高级特性
JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系
二、SpringDataJPA使用
1- 基本CRUD
运行步骤:
- 继承 JpaRepository
public interface UserMapper extends JpaRepository<User, Long> {
}
- 使用dao操作
findOne(id) :根据id查询
save(customer):保存或者更新(依据:传递的实体类对象中,是否包含id属性)
delete(id) :根据id删除
findAll() : 查询全部
2- 基本查询
1.Spring Data JPA 中接口定义的方法进行查询
也就是JpaRepository中包含的查询方法
分页查询
Spring Boot Jpa 已经帮我们实现了分页的功能,在查询的方法中,需要传入参数Pageable
。
Page<User> findALL(Pageable pageable); 和 Page<User> findByUserName(String userName,Pageable pageable);
限制查询
查询前N个元素
User findTopByOrderByAgeDesc();
Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
2.JPQL 的方式查询
使用jpql的语句查询
//@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引
@Query(value="from Customer where custName = ?1") public Customer findCustomer(String custName);
3.SQL 语句查询
在 SQL 的查询方法上面使用**@Query
注解,如涉及到删除和修改在需要加上@Modifying
.也可以根据需要添加 @Transactional
对事务的支持**。
/**
* nativeQuery : 使用本地sql的方式查询
*/
@Query(value="select * from cst_customer",nativeQuery=true)
public void findSql();
4.方法命名规则查询
按照 Spring Data JPA 提供的方法命名规则定义方法的名称,就可以完成查询工作。Spring Data JPA 在程序执行 的时候会根据方法名称进行解析,并自动生成查询语句进行查询。
按照 Spring Data JPA 定义的规则,查询方法以 findBy 开头,涉及条件查询时,条件的属性 用条件关键字连接,要注意的是:条件属性首字母需大写。框架在进行方法名解析时,会先把方法 名多余的前缀截取掉,然后对剩下部分进行解析。
3- Specifications 动态查询
需要DAO层继承JpaSpecificationExecutor
接口,通过该接口的方法查询。
@Test
public void testSpecifications () {
//使用匿名内部类的方式,创建一个Specification的实现类,并实现toPredicate方法
Specification<Customer> spec = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query,
CriteriaBuilder cb) {
//cb:构建查询,添加查询方式 like:模糊匹配
// 代表一个顶层查询对象,用来自定义查询
//root:从实体Customer对象中按照custName属性进行查询
return cb.like(root.get("custName").as(String.class), "传智播客%");
}
};
Customer customer = customerDao.findOne(spec);
System.out.println(customer);
}
4- 多表查询
系统三种实体关系分别为:多对多、一对多和一对一关系。
一对多
客户和联系人的一对多关系
Customer (1) ------- LinkMan(多)
Customer 实体类:
//配置客户和联系人的一对多关系 @OneToMany(targetEntity=LinkMan.class) @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id") private Set<LinkMan> linkmans = new HashSet<LinkMan>(0);
LinkMan实体类:
//多对一关系映射:多个联系人对应客户@ManyToOne(targetEntity=Customer.class)@JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")private Customer customer;
@OneToMany:
- 作用:建立一对多的关系映射
- 属性:
- targetEntityClass:指定多的多方的类的字节码
- mappedBy:指定从表实体类中引用主表对象的名称。
- cascade:指定要使用的级联操作
- fetch:指定是否采用延迟加载
- orphanRemoval:是否使用孤儿删除
@ManyToOne
- 作用:建立多对一的关系
- 属性:
- targetEntityClass:指定一的一方实体类字节码
- cascade:指定要使用的级联操作
- fetch:指定是否采用延迟加载
- optional:关联是否可选。如果设置为 false,则必须始终存在非空关系。
@JoinColumn
- 作用:用于定义主键字段和外键字段的对应关系。
- 属性:
- name:指定外键字段的名称
- referencedColumnName:指定引用主表的主键字段名称
- unique:是否唯一。默认值不唯一
- nullable:是否允许为空。默认值允许。
- insertable:是否允许插入。默认值允许。
- updatable:是否允许更新。默认值允许。
- columnDefinition:列的定义信息。
多对多
一个用户可以具有多个角色
一个角色也有多个用户
用户
//多对多关系映射@ManyToMany(mappedBy="users")private Set<SysRole> roles = new HashSet<SysRole>(0);
角色
//多对多关系映射@ManyToMany@JoinTable(name = "user_role_rel",//中间表的名称 //中间表user_role_rel字段关联sys_role表的主键字段role_id joinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "role_id")}, //中间表user_role_rel的字段关联sys_user表的主键user_id inverseJoinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "user_id")})private Set<SysUser> users = new HashSet<SysUser>(0);
@ManyToMany
- 作用:用于映射多对多关系
- 属性:
- cascade:配置级联操作。
- fetch:配置是否采用延迟加载。
- targetEntity:配置目标的实体类。映射多对多的时候不用写。
@JoinTable
- 作用:针对中间表的配置
- 属性:
- name:配置中间表的名称
- joinColumns:中间表的外键字段关联当前实体类所对应表的主键字段
- inverseJoinColumn:中间表的外键字段关联对方表的主键字段
三、其他
1- 多数据源的支持
同源数据库的多源支持
日常项目中因为使用的分布式开发模式,不同的服务有不同的数据源,常常需要在一个项目中使用多个数据源,因此需要配置 Spring Boot Jpa 对多数据源的使用,一般分一下为三步:
- 1 配置多数据源
- 2 不同源的实体类放入不同包路径
- 3 声明不同的包路径下使用不同的数据源、事务支持
异构数据库多源支持
比如我们的项目中,即需要对 mysql 的支持,也需要对 Mongodb 的查询等。
实体类声明@Entity
关系型数据库支持类型、声明@Document
为 Mongodb 支持类型,不同的数据源使用不同的实体就可以了
interface PersonRepository extends Repository<Person, Long> { …}@Entitypublic class Person { …}interface UserRepository extends Repository<User, Long> { …}@Documentpublic class User { …}
但是,如果 User 用户既使用 Mysql 也使用 Mongodb 呢,也可以做混合使用
interface JpaPersonRepository extends Repository<Person, Long> { …}interface MongoDBPersonRepository extends Repository<Person, Long> { …}@Entity@Documentpublic class Person { …}
也可以通过对不同的包路径进行声明,比如 A 包路径下使用 mysql,B 包路径下使用 MongoDB
@EnableJpaRepositories(basePackages = "com.neo.repositories.jpa")@EnableMongoRepositories(basePackages = "com.neo.repositories.mongo")interface Configuration { }
2- 使用枚举
使用枚举的时候,我们希望数据库中存储的是枚举对应的 String 类型,而不是枚举的索引值,需要在属性上面添加@Enumerated(EnumType.STRING)
注解
@Enumerated(EnumType.STRING) @Column(nullable = true)private UserType type;
3- 不需要和数据库映射的属性
正常情况下我们在实体类上加入注解@Entity
,就会让实体类和表相关连如果其中某个属性我们不需要和数据库来关联只是在展示的时候做计算,只需要加上@Transient
属性既可。
@Transientprivate String userName;
参考或相关文章
http://www.ityouknow.com/springboot/2016/08/20/spring-boot-jpa.html