SpringData 基础篇

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: SpringData 基础篇

Spring Data

五:总结&提升

故事背景

最近学习SpringData,系统的总结一下SpringData的相关知识,此篇为算是一篇前言,主要介绍一下SpringData,先讲一个JPA和Hibernate,讲一讲他们的关系,并且给出对应的示例,希望大家可以通过这个示例,了解到这些概念以及其基本的用法。


一:基础概念

1.1 什么是SpringData

Spring Data是Spring Framework的一个子项目,它提供了一种简化数据访问层的方式。它的目标是提供一种统一的、易于使用的编程模型,用于与不同类型的数据存储进行交互,包括关系型数据库、NoSQL数据库、图数据库等。

1.2 为什么要用SpringData

其统一和简化了对不同数据库类型的持久化。通过使用SpringData我们可以简化开发,提升开发效率。

springData是一个伞型项目,有多个子项目,不同的子项目针对不同的数据库的实现。

二:JPA与Hibernate、MyBatis关系

2.1 JPA与JDBC

2.1.1 特点

二者都是与数据库交互的规范。数据库实现了JDBC的规范。ORM(Object、Relational、mapping)框架实现了JPA的规范。

JDBC通过sql语句与数据库通信。JPA用面向对象的方式,通过ORM生成SQL,进行操作。

JPA 是需要 JDBC的,是依赖于JDBC的。

2.1.2 JPA规范提供

ORM映射元数据,注解和xml两种方式

JPA的API,用来操作对象,执行对应的CRUD的操作,让开发者从JDBC和SQL代码中解脱出来

JPQL查询语言,通过面向对象的方式,面向数据库查询

2.1.3 JDBC的不足

学习成本高

修改不同数据库时,不容易移植

JAVA对象和数据库的映射比较麻烦

2.2 Hibernate与JPA

2.2.1 关系

Hibernate实现了JPA规范。是JPA的一种实现。

2.3 mybatis 和Hibernate

MyBatis是一个半自动的ORM框架,需要自己写sql。而Hibernate是全自动的ORM框架

MyBatis更加小巧,是对JDBC的封装。Hibernate根据ORM直接生成不同的SQL

MyBatis在国内比较流行,关系比较复杂。Hibernate在国外更加流行,Hibernate不是很适合复杂的关系

三:Hibernate与JPA快速搭建

3.1 新建一个Maven项目并引入对应Pom依赖

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.4.32.Final</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>

3.2 hibernate具体配置

需要在我们的Resource目录下,添加对应的配置,这里先添加Hibernate对应的配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- 数据库连接配置 -->
        <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/jpa</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root666</property>
        <property name="hibernate.connection.characterEncoding">UTF-8</property>
        <property name="hibernate.connection.useUnicode">true</property>
        <!--        日志中记录sql-->
        <property name="show_sql">true</property>
        <!--        格式化sql-->
        <property name="format_sql">true</property>
        <!--        表的生成策略,自动生成-->
        <property name="hbm2ddl.auto">update</property>
        <!-- 数据库方言,注意版本 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</property>
        <!-- 映射文件位置 -->
        <mapping class="org.example.entity.User"/>
    </session-factory>
</hibernate-configuration>

此配置文件主要是配置我们对应的数据库,以及一些对应的主要功能的配置,我将重要配置都加上了注释。

3.3. 具体使用Hibernate实现操作

3.3.1 项目结构

首先宏观看一下项目结构,这样有利于下面的讲解:

3.3.2 User类

User类是一个实体类,对应数据库表

@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private long id;
    private String userName;
    private String email;
  //get与set 略 

}

这里主要是几个注解来进行标识:


@Entity注解

表示我们的User类是一个实体类,其应该在数据库内对应一张表

@Table注解

通过Table注解可以指定对应的表的名称

@Id注解

每个实体类必须要有一个主键Id,对应数据库表的主键,Id有多种生成策略

@GeneratedValue注解

指定主键的生成策略,这里使用的是自增的形式

3.3.3 HibernateTest 实现

public class HibernateTest {
    //Session工厂 代码持久化到数据库的一个桥梁
    private SessionFactory sf;
    @Before
    public void  init() {
        StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure("/hibernate.cfg.xml").build();
        sf = new MetadataSources(registry).buildMetadata().buildSessionFactory();
    }
    @Test
    public void test(){
        //session 进行持久化操作
        try(Session session = sf.openSession()){
            Transaction tx = session.beginTransaction();
            User user = new User();
            user.setUserName("郝立琢");
            user.setEmail("123456@163.com");
            session.save(user);
            tx.commit();
        }
    }
    @Test
    public void test1(){
        try(Session session = sf.openSession()){
            Transaction tx = session.beginTransaction();
            User user = session.find(User.class,1L);
            tx.commit();
            System.out.println(user.getUserName());
        }
    }

通过Session会话实现数据库的插入和查询两种操作。

3.4 JPA具体配置

3.5 具体使用JPA进行实现

3.5.1 添加配置文件

首先在Resource下新增一个名为 MEAT-INF的文件夹,然后再其内部增添一个名为persistence的xml文件

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <!-- 需要配置persistence-unit节点
    持久化单元:
    name:持久化单元名称
    transaction-type:事务管理的方式
    JTA:分布式事务管理
    RESOURCE_LOCAL:本地事务管理 -->
    <persistence-unit name="hibernateJPA" transaction-type="RESOURCE_LOCAL">
        <!-- jpa的实现方式 -->
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>org.example.entity.User</class>
        <!-- 可选配置:配置jpa实现方的配置信息 -->
        <properties>
            <!-- 数据库信息
            用户名,javax.persistence.jdbc.user
            密码,javax.persistence.jdbc.password
            驱动,javax.persistence.jdbc.driver
            数据库地址,javax.persistence.jdbc.url -->
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="root666"/>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa?serverTimezone=UTC"/>
            <!-- 配置jpa实现方(hibernate)的配置信息
            显示sql:false|true
            自动创建数据库表:hibernate.hbm2ddl.auto
            create:程序运行时创建数据库表(如果有表,先删除表再创建)
            update:程序运行时创建表(如果有表,不会创建表)
            none:不会创建表 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/>
        </properties>
    </persistence-unit>
</persistence>

此处为JPA对应的配置,主要定义了持久化单元、指定了JPA实现的提供者、配置实体类、配置了相关属性。

3.5.2 测试类

public class JpaTest {
        //EntityManagerFactory类型的属性,用于创建EntityManager对象。
    private EntityManagerFactory factory;
    //是EntityManager类型的属性,用于执行JPA操作,包括实体的持久化、更新、查询等。
    EntityManager em;
    @Before
    public void inti(){
        //加载配置文件
        factory = Persistence.createEntityManagerFactory("hibernateJPA");
        //获取EntityManager对象
        em = factory.createEntityManager();
    }
    /**
     * 查询全部
     * jqpl:from cn.itcast.domain.Customer
     * sql:SELECT * FROM cst_customer
     */
    @Test
    public void testR_HQL() {
        //2.开启事务
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        //3.查询全部
        String jpql = "select c from User c";
        Query query = em.createQuery(jpql);//创建Query查询对象,query对象才是执行jqpl的对象
        //发送查询,并封装结果集
        List list = query.getResultList();
        for (Object obj : list) {
            User user = (User)obj;
            System.out.print(user.getUserName());
        }
        //4.提交事务
        tx.commit();
        //5.释放资源
        em.close();
    }
    @Test
    public void testR() {
        //2.开启事务
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        User user = em.getReference(User.class, 1L);
        System.out.println("===========================");
        System.out.println(user);
        //4.提交事务
        tx.commit();
        //5.释放资源
        em.close();
    }
}

使用JPA的规范进行的调用,我们可以更好的移植其他对JPA的实现。


四:JPA中对象的四种状态

4.1 jpa的对象4种状态

临时状态:刚创建出来,∙没有与entityManager发生关系,没有被持久化,不处于entityManager中的对象

持久状态:∙与entityManager发生关系,已经被持久化,您可以把持久化状态当做实实在在的数据库记录。

删除状态:执行remove方法,事物提交之前

游离状态:游离状态就是提交到数据库后,事务commit后实体的状态,因为事务已经提交了,此时实体的属

性任你如何改变,也不会同步到数据库,因为游离是没人管的孩子,不在持久化上下文中。

4.2 persist方法

public void persist(Object entity)

persist方法可以将实例转换为managed(托管)状态。在调用flush()方法或提交事物后,实

例将会被插入到数据库中。

对不同状态下的实例A,persist会产生以下操作:


如果A是一个new状态的实体,它将会转为managed状态;

如果A是一个managed状态的实体,它的状态不会发生任何改变。但是系统仍会在数据库执行INSERT操作;

如果A是一个removed(删除)状态的实体,它将会转换为受控状态;

如果A是一个detached(分离)状态的实体,该方法会抛出IllegalArgumentException异常,具体异常根据不同的

JPA实现有关。

4.3 merge方法

public void merge(Object entity)

merge方法的主要作用是将用户对一个detached状态实体的修改进行归档,归档后将产生

一个新的managed状态对象。

对不同状态下的实例A,merge会产生以下操作:


如果A是一个detached状态的实体,该方法会将A的修改提交到数据库,并返回一个新的managed状态的实例A2;

如果A是一个new状态的实体,该方法会产生一个根据A产生的managed状态实体A2;

如果A是一个managed状态的实体,它的状态不会发生任何改变。但是系统仍会在数据库执行UPDATE操作;

如果A是一个removed状态的实体,该方法会抛出IllegalArgumentException异常。

4.4 refresh方法

public void refresh(Object entity)

refresh方法可以保证当前的实例与数据库中的实例的内容一致。

对不同状态下的实例A,refresh会产生以下操作:


如果A是一个new状态的实例,不会发生任何操作,但有可能会抛出异常,具体情况根据不同JPA实现有关;

如果A是一个managed状态的实例,它的属性将会和数据库中的数据同步;

如果A是一个removed状态的实例,该方法将会抛出异常: Entity not managed

如果A是一个detached状态的实体,该方法将会抛出异常。

4.5 remove方法

public void remove(Object entity)

remove方法可以将实体转换为removed状态,并且在调用flush()方法或提交事物后删除数据库中的数据。

对不同状态下的实例A,remove会产生以下操作:


如果A是一个new状态的实例,A的状态不会发生任何改变,但系统仍会在数据库中执行DELETE语句;

如果A是一个managed状态的实例,它的状态会转换为removed;

如果A是一个removed状态的实例,不会发生任何操作;

如果A是一个detached状态的实体,该方法将会抛出异常

五:总结&提升

本文主要讲解了SpringData的基本概念,以及什么是JPA,JPA与我们熟知的Hibernate、MyBatis之间的关系。并且给出了Hibernate和JPA的具体示例代码,通过此文,我们可以了解到什么是JPA,了解JPA规范的作用,为我们接下来深入学习SpringData打下基础。


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
开发框架 前端开发 Java
SpringBootWeb、SpringMVC、SpringBoot三者关系和底层剖析
这是关于SpringBootWeb、SpringMVC、SpringBoot三者关系和剖析底层, 以及Web应用的帖子
160 0
|
SQL 安全 Java
SpringData JPA(2)
SpringData JPA(2)
124 1
|
存储 NoSQL Java
SpringData快速入门
SpringData快速入门
|
Java
30SpringBoot整合SpringData JPA
30SpringBoot整合SpringData JPA
50 0
|
6月前
|
XML 安全 IDE
springboot @RequiredArgsConstructor的概念与使用
【4月更文挑战第25天】在Spring Boot中,@RequiredArgsConstructor注解是Lombok库提供的功能,用于自动生成包含必需参数的构造函数。"必需参数"指的是那些被声明为final或者有@NonNull注解的成员变量。这种注解极大地简化了Java类的编写,尤其是在需要注入依赖或常量值时
269 3
|
Java 数据库连接 mybatis
flowable项目启动项目报错:Consider defining a bean of type ‘org.mybatis.spring.SqlSessionTemplate‘ in ……
flowable项目启动项目报错:Consider defining a bean of type ‘org.mybatis.spring.SqlSessionTemplate‘ in ……
313 0
|
6月前
|
SQL Java 关系型数据库
SpringBoot整合SpringData与JPA
SpringBoot整合SpringData与JPA
81 0
|
存储 NoSQL Java
SpringData JPA(1)
SpringData JPA(1)
100 0
|
Java 测试技术 API
SpringBoot 整合 Dozer 映射框架
SpringBoot 整合 Dozer 映射框架
453 0
SpringBoot 整合 Dozer 映射框架
|
SQL Java 数据库连接
SpringData JPA(提升篇)
🍅程序员小王的博客:程序员小王的博客 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 如有编辑错误联系作者,如果有比较好的文章欢迎分享给我,我会取其精华去其糟粕 🍅java自学的学习路线:java自学的学习路线
115 0
SpringData JPA(提升篇)