【java学习-Spring】Spring-data-jpa(Java Persistence API) - Go语言中文社区

【java学习-Spring】Spring-data-jpa(Java Persistence API)


1,概念

JPA的存在意义是为了整合第三方ORM框架,建立一种标准的方式ORM 访问数据库的统一。但是现阶段JPA几乎都是接口,实现都是Hibernate在做。我们都知道,在使用持久化工具的时候,一般都有一个对象来操作数据库,在原生的Hibernate中叫做Session,在MyBatis中叫做SqlSession,而在JPA中叫做EntityManager通过这个对象来操作数据库。

对象关系映射(Object Relational Mapping,简称ORM)
通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。

2,原理

1)Repository接口

在这里插入图片描述

Repository

最顶层的接口,是一个空接口,目的是为了统一所有的Repository的类型,且能让组件扫描时自动识别。

CrudRepository

Repository的子接口,提供CRUD 的功能。

PagingAndSortingRepository

CrudRepository的子接口, 添加分页排序。

JpaRepository

PagingAndSortingRepository的子接口,增加批量操作等。

常用方法

delete删除或批量删除 
findOne查找单个 
findAll查找所有 
save保存单个或批量保存 
saveAndFlush保存并刷新到数据库

JpaSpecificationExecutor

用来做复杂查询的接口。

2)启动过程

由于引入了starter-data-jpa,自动配置,spring启动时会实例化一个Repositories,然后扫描包,找出所有继承Repository的接口(除@NoRepositoryBean注解的类),遍历装配。为每一个接口创建相关实例。
SimpleJpaRespositry——用来进行默认的DAO操作,是所有Repository的默认实现
JpaRepositoryFactoryBean——装配bean,装载了动态代理Proxy,会以对应的DAO的beanName为key注册到DefaultListableBeanFactory中,在需要被注入的时候从这个bean中取出对应的动态代理Proxy注入给DAO
JdkDynamicAopProxy——动态代理对应的InvocationHandler,负责拦截DAO接口的所有的方法调用,然后做相应处理,比如findByUsername被调用的时候会先经过这个类的invoke方法

导入jpa,自动配置扫描包内所有继承了Repository接口的接口,为每一个接口实例一个代理类(SimpleJpaRepository),并为每个方法确定一个query策略,已经其他所需的bean,使用自定的repository时,是使用的代理类,经过一些列的拦截器后,选取一个query执行器JpaQueryExecution,然后创建Query对象,拼接sql,组装参数等DB操作,最后返回Query.getResultList()。

3,使用

1)maven配置以及相关数据库依赖配置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.1.7.RELEASE</version>
</dependency>

2)实体类

@Table(name=userinfoTab) 
@Entity 
public class Userinfo implements Serializable {
    @Id  //映射到数据库表的主键属性
    @GeneratedValue(strategy=GenerationType.AUTO)  //主键的生成策略(自增)
    private Long user_id;
    private String user_name;
    @Column(length = 255) //配置单列属性
    private String user_tel;
    @Transient
    private String new_time;
	...
}

@Entity

声明这个类是一个实体类,必写

@Table(name=userinfoTab)

指定映射到数据库的表格。
name 表名
catalog 设置表所属的数据库目录
schema 设置表所属的模式

@Id

映射到数据库表的主键属性

@GeneratedValue(strategy=GenerationType.AUTO)

主键的生成策略。
IDENTITY:采用数据库 ID自增长的方式来自增主键字段,Oracle 不支持这种方式;
AUTO: JPA自动选择合适的策略,是默认选项;默认情况下,SqlServer 对应 identity,MySQL 对应 auto increment。
SEQUENCE:通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式
TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。

@Basic

@Basic 表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的 getXxxx() 方法,默认即为
@Basic fetch: 表示该属性的读取策略,有 EAGER 和 LAZY 两种,分别表示主支抓取和延迟加载,默认为 EAGER.
optional:表示该属性是否允许为null, 默认为true

@Column

当实体的属性与其映射的数据库表的列不同名时需要使用@Column 标注说明,该属性通常置于实体的属性声明语句之前,还可与 @Id 标注一起使用。
name 设置映射数据库表的列名
unique 、nullable、length 等。

@Transient

表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性.

@Temporal

数据库中,表示 Date 类型的数据有 DATE, TIME, 和 TIMESTAMP 三种精度。在进行属性映射时可使用@Temporal注解来调整精度。

@Temporal(TemporalType.TIMESTAMP)// 时间戳
    public Date getCreatedTime() {
        return createdTime;
        }

@Temporal(TemporalType.DATE) //时间精确到天
    public Date getBirth() {
        return birth;
    }

3)Repository接口

JPQL(面向对象的SQL语法结构)

public interface UserinfoRepository extends JpaRepository<Userinfo, Long> {
    @Modifying
    @Query(value = "update userinfo set user_name = :name, user_tel = :tel where user_id = :id",nativeQuery = true)
    void updateById(@Param("id") Long id, @Param("name") String name, @Param("tel") String tel);

    @Query(value = "select user_id from userinfo",nativeQuery = true)
    List<Long> getUserIdList();
}

以上类通常放在dao包下面。
外部使用时:

    @Autowired
    ThreatRepository threatRepository;

     threatRepository.saveAll(list);

分页查询

import org.springframework.data.domain.Pageable;
@Query(value = "SELECT* FROM stu_tab ",nativeQuery = true)
    List<ThreatEntity> getThreatTrend_3h(Pageable pageable);
@RequestMapping(value = "/testPageable", method = RequestMethod.GET)
public Page<User> testPageable(
        @RequestParam("page") Integer page,  //页码
        @RequestParam("size") Integer size,    //每页数量 
        @RequestParam("sortType") String sortType,  //排序方式:ASC/DESC
        @RequestParam("sortableFields") String sortableFields  //排序字段
) {
    //判断排序类型及排序字段
    Sort sort = "ASC".equals(sortType) ? new Sort(Sort.Direction.ASC, sortableFields) : new Sort(Sort.Direction.DESC, sortableFields);
    //获取pageable
    Pageable pageable = new PageRequest(page-1,size,sort);
    return userRepository.findAll(pageable);
}

踩坑:sql语句中有distinct但无order by。加入pageable后报错如下:

SELECT DISTINCT ON expressions must match initial ORDER BY expressions

原因是:
1,在sql中当order by和distinct同时使用时,如果指定了 SELECT DISTINCT,那么 ORDER BY 子句中的项就必须出现在选择列表中。
2,在sql中加入order by语句即可解决该问题。
3,pageable 中 的sort会自动在sql后面拼接order by语句。

解析方法名创建查询

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/SunshineTan/article/details/99847676
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢