简述:
1、简化代码开发,自动生成了各种CRUD的接口方法,不需要收到写SQL
Springdata Repository
1、CurdRepository
public interface CrudRepository<T, ID> extends Repository<T, ID> {
// 用了插入和修改,有主键就是修改,没主键就是插入
//获得插入后的ID
<S extends T> S save(S entity);
//批量插入
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
Optional<T> findById(ID id);
boolean existsById(ID id);
Iterable<T> findAll();
//根据ID批量查询
Iterable<T> findAllById(Iterable<ID> ids);
long count();
void deleteById(ID id);
void delete(T entity);
void deleteAllById(Iterable<? extends ID> ids);
void deleteAll(Iterable<? extends T> entities);
void deleteAll();
}
2、PagingAndSortingRepository 继承CrudRepository
1、分页和排序的接口
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
2、分页,里面也可以排序
3、排序
Sort.TypedSort<Custom> sortType = Sort.sort(Custom.class);
// id正序,姓名倒叙排序
sortType.by(Custom::getId).ascending().and(sortType.by(Custom::getName).descending());
自定义Repository
查看hibernate官方文档:
Hibernate ORM 6.2.6.Final User Guide
public interface CustomRepository extends JpaRepository<Custom, BigInteger>, PagingAndSortingRepository<Custom, BigInteger> {
/**
* jpql:原生SQL
* 1、@Query 查询实体
* ?数字:索引方式查询,1代表第一个参数
* 具体名:通过@Param指定
*
*
*/
// @Query("from Custom where name=?1")
@Query("from Custom where name=:customName")
Custom findByName(@Param("customName") String customName);
/**
* 增删改必须指定事务和修改注解
*/
@Transactional
@Modifying
@Query("update Custom set name=?1 where id=?2")
int crudCus(String name, BigInteger id);
/**
* 插入name这一个列
*/
@Query("INSERT into Custom (name) select c.name from Custom c")
void insertCus(Custom custom);
/**
* 2、如果操作原生的表必须指定:nativeQuery=true
*
*
*/
// @Query("from Custom where name=?1")
// @Query("from Custom where name=:customName")
@Query(value = "select * from custon where name=:customName", nativeQuery = true)
Custom findByName(@Param("customName") String customName);
}
官方规定方法名格式得到想要的数据 (规定方法名)
1、规定方法名
2、谓词条件
3、规定方法名,直接根据By后面的字段操作过程了
动态条件查询 -
Query By Example
1、不支持嵌套或分组的属性约束如: firstName=?1 or ( firstName=?1 and lastNAme=?2)
2、只支持字符串的 start/contains/end/regex 函数匹配和 其他属性的精确匹配
将Reposiory继承QueryByExampleExecutor
public void example(){
Custom custom = new Custom();
custom.setName("aa");
/**
* Example进行多参数匹配 配合ExampleMatcher
*/
ExampleMatcher exampleMatcher = ExampleMatcher.matching()
.withIgnorePaths("name")// 忽略查询属性
.withIgnoreCase("name")// 忽略大小写
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)// 对所有包含匹配
.withMatcher("name", matcher -> matcher.contains());//对单个属性进行模糊匹配
Example<Custom> example = Example.of(custom, exampleMatcher);
//
List<Custom> list = (List<Custom>) repository.findAll(example);
}
通过QueryDsl 通用的查询(支持jpa mongoDB,sql jdo)(比Specification简单)
继承 QuerydslPredicateExecutor
1、需要导入依赖包--去查询一下
2、写SQL方式查询 em ->EntityManager
通过Specification进行查询
继承 JpaSpecificationExecutor
public void example(){
List<Custom> list = repository.findAll(new Specification<Custom>() {
/**
* 注意: 如果设置动态的条件 就需要定义一个接受的类 通过获取属性来进行
* Person
* name
* address
*
* @param root 理解成 from 从custom获取列
* @param query 组合 (order by 、where)
* @param criteriaBuilder 理解从 where 设置各种条件(> < =)
* @return
*/
@Override
public Predicate toPredicate(Root root, CriteriaQuery query,
CriteriaBuilder criteriaBuilder) {
Path name = root.get("name");
Path address = root.get("address");
// 参数1:哪个字段 参数2:设置值
Predicate preName = criteriaBuilder.equal(name, "33");
Predicate preAddress = criteriaBuilder.like(name, "%33%");
// 多个条件组合返回,
Predicate and = criteriaBuilder.and(preName, preAddress);
// 这样and 和or 就是一个条件了
Predicate or = criteriaBuilder.or(and, preAddress);
// 设置排序字段
Order nameDesc = criteriaBuilder.desc(name);
// 设置排序 getRestriction 条件
Predicate restriction = query.where(or).orderBy(nameDesc)
.getRestriction();
return restriction;
}
});
hibernage原生的方式进行分组和求和进行EntityManager
JPA 关联查询 OneToOne OneToMany ..
springjap没有提供多表关联,所以去hibernate官方文档找
1、参考文档:Hibernate ORM 5.5.9.Final User Guide
@OneToOne
1、查询不需要双向关联
2、FetchType=LAZY : 懒加载要调用方法上面配置事务readOnly=true,因为repository调用完之后会立即关闭session
3、orphanRemoval = true:关联移除,通常修改的时候使用
一般把关联数据设置为null 或者修改为其他关联数据,一般把orphanRemoval=true
@Entity
@Table
public class Custom {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private BigInteger id;
private String name;
private String address;
/**
* cascade = CascadeType. :如果不加的话,所有的(除了查询)操作只针对主表一张表
* PERSIST:只有插入操作Person也进行插入
* ALL : 所有操作都会带上Person
* MERGE:只有修改操作
* REMOVE:只有删除操作
*
* fetch = FetchType.LAZY :懒加载 fetch = FetchType.EAGER立即加载
*/
@OneToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER
,orphanRemoval = true)
@JoinColumn(name="personName")
private Person person;
}
@Getter
@Setter
@Entity
@Table
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private BigInteger id;
private String personName;
private BigInteger cosId;
/**
* 当双向关联的时候, 主表和字表都不能单独操作删除了。
* 只能把外键约束交个一方维护:mappedBy=custom
*/
@OneToOne(mappedBy = "custom")
@JoinColumn(name="personName")
private Custom custom;
}
@OneToMany
1、外键维护在多的一方
2、一对多默认懒加载,查询的时候得加@Transcation(readOnly=true)
error: no-session
/**
* @JoinColumn(name = "cusId") 外键名称
*/
@OneToMany
@JoinColumn(name = "cusId")
private List<Order> orderList;
@ManyToOne 多对一
1、多对一插入 符合实际开发场景
@ManyToMany
1、一般维护一张中间表
2、JoinTable name="中间表的名字"
3、joinColumn='本表的外键'
4、inverseJoinColums:关联表的外键名称
乐观锁
1、防止并发情况下共享数据的误操作
2、实现:private @Version Long version;
private @Version Long version;
审计