Spring Data Jpa

2023-11-05

spring data介绍

Spring Data’s mission is to provide a familiar and consistent, Spring-based programming model for data access while still retaining the special traits of the underlying data store.

It makes it easy to use data access technologies, relational and non-relational databases, map-reduce frameworks, and cloud-based data services. This is an umbrella project which contains many subprojects that are specific to a given database. The projects are developed by working together with many of the companies and developers that are behind these exciting technologies.

Spring Data的使命是为数据访问提供熟悉且一致的基于Spring的编程模型,同时仍保留底层数据存储的特殊特性。

它使数据访门技术,关系数是库和非关系数据库,mag-redhce框架和基于云的数据服务变得简单易用。这是一个伞形项目,其中包含许多特定于给定数据库的子项目。这些项目是通过与这些激动人心的技术背后的许多公司和开发人员合作开发的。

人话:

Spring Data致力为数据访问(DAO)提供熟悉且一致的基于Spring的编程模板;

对于每种持久性存储,您的DAO通常需要为不同存储库提供对不同CRUD(创建-读取-更新-删除)持久化操作。Sping Data为这些持久性存储以及特定实现提供了通用接口(CrudReposory、PagingAndSortingRepository)和模板(jdbcTemplate,redisTemplate,RestTemplate,MongoTemplate...)。

其目的是统一和简化对不同类型持久性存储(关系数据库系统和NoSQL数据存储)的访问。

Spring Data

spring data 主要模块

各模块使用率

spring data 主要特性 

什么是JPA?

相同处:
1.都跟数据库操作有关,JPA 是JDBC 的升华,升级版。
2.JDBC和JPA都是一组规范接口
3.都是由SUN官方推出的
不同处:
1.JDBC是由各个关系型数据库实现的, JPA 是由 ORM框架 实现
2.JDBC 使用SQL语句和数据库通信。 JPA用面向对象方式, 通过ORM框架来生成SQL,进行操作。
3.JPA在JDBC之上的, JPA也要依赖JDBC才能操作数据库。

JDBC是我们最熟悉的用来操作数据库的技术,但是随之而来带来了一些问题:
1. 需要面向SQL语句来操作数据库,开发人员学习成本更高。
2. 数据库的移至性不高,不同数据库的SQL语句无法通用。
3. java对象和数据库类型的映射是个麻烦事。
但在Sun在JDK1.5提出了JPA:
JPA全称Java Persistence API(
2019年重新命名为 Jakarta Persistence API ), 是Sun官方提出的 一种ORM规范。
O:Object R: Relational M:mapping
作用
1.简化持久化操作的开发工作:让 开发者从繁琐的 JDBC 和 SQL 代码中解脱出来,直接面向对象持久化操作。
2.Sun希望持久化技术能够统一,实现天下归一:如果你是基于JPA进行持久化你可以随意切换数据库。
该规范为我们提供了:
1) ORM映射元数据 :JPA支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对
象持久化到数据库表中;
如: @Entity @Table @Id @Column 等注解。
2) JPA 的API :用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和
SQL代码中解脱出来。
如: entityManager.merge(T t)
3) JPQL查询语言 :通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
如: from Student s where s.name = ?
So: JPA仅仅是一种规范,也就是说JPA仅仅定义了一些接口,而接口是需要实现才能工作的。

Hibernate与JPA:

 所以底层需要某种实现,而Hibernate就是实现了JPA接口的ORM框架。

也就是说:
JPA是一套ORM规范,Hibernate实现了JPA规范!

mybatis:小巧、方便?、高效、简单、直接、半自动
半自动的ORM框架,
小巧: mybatis就是jdbc封装
在国内更流行。
场景: 在业务比较复杂系统进行使用,
hibernate:强大、方便、高效、(简单)复杂、绕弯子、全自动
全自动的ORM框架,
强大:根据ORM映射生成不同SQL
在国外更流。
场景: 在业务相对简单的系统进行使用,随着微服务的流行。

Hibernate示例

Hibernate ORM 5.5.9.Final User Guide (jboss.org)

我们来实现一个Hibernate来示例感受下:
创建maven项目
pom.xml
<!--junit4-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>

        <!--hibernate对jpa的支持包-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.4.32.Final</version>
        </dependency>

        <!-- Mysql and MariaDB-->
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
实体类
package com.wzh.pojo;

import javax.persistence.*;

@Entity  //作为hibernate实体类
@Table(name = "tal_customer")   //表的映射
public class Customer {
    /**
     * @Id:声明主键的配置
     * @GeneratedValue:配置主键的生成策略 strategy
     * GenerationType.IDENTITY :自增,mysql
     * * 底层数据库必须支持自动增长(底层数据库支持的自动增长方式,对id自增)
     * GenerationType.SEQUENCE : 序列,oracle
     * * 底层数据库必须支持序列
     * GenerationType.TABLE : jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
     * GenerationType.AUTO : 由程序自动的帮助我们选择主键生成策略
     * @Column:配置属性和字段的映射关系 name:数据库表中字段的名称
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cust_id")
    private Long custId; //客户的主键

    @Column(name = "cust_name")
    private String custName;//客户名称

    @Column(name = "cust_address")
    private String custAddress;//客户地址

    public Long getCustId() {
        return custId;
    }

    public void setCustId(Long custId) {
        this.custId = custId;
    }

    public String getCustName() {
        return custName;
    }

    public void setCustName(String custName) {
        this.custName = custName;
    }


    public String getCustAddress() {
        return custAddress;
    }

    public void setCustAddress(String custAddress) {
        this.custAddress = custAddress;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "custId=" + custId +
                ", custName='" + custName + '\'' +
                ", custAddress='" + custAddress + '\'' +
                "}\n";
    }
}
hibernate.cfg.xml(在resource下创建)
<?xml version="1.0" encoding="GBK"?>
<!-- 指定Hibernate配置文件的DTD信息 -->
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- hibernate- configuration是连接配置文件的根元素 -->
<hibernate-configuration>
    <session-factory>
        <!-- 指定连接数据库所用的驱动 -->
        <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <!-- 指定连接数据库的url,hibernate连接的数据库名 -->
        <property name="connection.url">jdbc:mysql://localhost:3306/springdata_jpa?serverTimezone=Asia/Shanghai</property>
        <!-- 指定连接数据库的用户名 -->
        <property name="connection.username">root</property>
        <!-- 指定连接数据库的密码 -->
        <property name="connection.password">123456</property>

        <!-- 指定数据库方言 ctrl+H  查看自己需要的数据库方言-->
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <!-- 根据需要自动创建数据表
                表的生成策略
                 默认none 不自动生成
                 update   如果没有表会创建,有会检查更新
                 create   创建
        -->
        <property name="hbm2ddl.auto">update</property>
        <!-- 显示Hibernate持久化操作所生成的SQL  会在日志中记录sql 默认false -->
        <property name="show_sql">true</property>
        <!-- 将SQL脚本进行格式化后再输出 -->
        <property name="format_sql">true</property>
        <!-- 罗列所有的映射文件 -->
        <mapping class="com.wzh.pojo.Customer"/>
    </session-factory>
</hibernate-configuration>
测试
package com.wzh;

import com.wzh.pojo.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

/**
 * @ProjectName: springDataJpa-demo
 * @Package: com.wzh
 * @ClassName: hibernateTest
 * @Author: 王振华
 * @Description:
 * @Date: 2023/4/16 15:25
 * @Version: 1.0
 */
public class hibernateTest {

    //session工厂   session:数据库会话  代码持久化操作数据库的一个桥梁
    private SessionFactory sf;

    @Before
    public void init() {
        StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure("/hibernate.cfg.xml").build();

        //2.根据服务注册类创建一个元数据资源集  同时构成元数据并生成应用一般唯一的session工厂
        sf = new MetadataSources(registry).buildMetadata().buildSessionFactory();
    }

    @Test
    public void testC() {
        // 创建Session
        try(Session sess = sf.openSession()) {
            // 开始事务
            Transaction tx = sess.beginTransaction();

            Customer customer = new Customer();
            customer.setCustName("张三");
            customer.setCustAddress("上海");

            sess.save(customer);
            // 提交事务
            tx.commit();
            // 关闭Session
            sess.close();
            sf.close();
        }
    }

    @Test
    public void testR() {
        // 创建Session
        try(Session sess = sf.openSession()) {
            // 开始事务
            Transaction tx = sess.beginTransaction();
            Customer customer = sess.find(Customer.class, 1L);
            System.out.println(customer.toString());
            // 提交事务
            tx.commit();
            // 关闭Session
            sess.close();
            sf.close();
        }
    }

    @Test
    public void testC_HQL() {
        // 创建Session
        Session sess = sf.openSession();
        // 开始事务
        Transaction tx = sess.beginTransaction();
        // 保存消息
        String hql = "insert into Customer (custName,custAddress) SELECT custName,custAddress FROM Customer ";

        sess.createQuery(hql)
                .executeUpdate();
        // 提交事务
        tx.commit();
        // 关闭Session
        sess.close();
        sf.close();
    }


    // 延迟查询
    @Test
    public void testR1() {
        // 创建Session
        Session sess = sf.openSession();
        // 开始事务
        Transaction tx = sess.beginTransaction();

        Customer customer = sess.load(Customer.class, 1L);
        System.out.println("=============================");
        System.out.println(customer);

        // 提交事务
        tx.commit();
        // 关闭Session
        sess.close();
        sf.close();
    }


    @Test
    public void testR_HQL_list() {
        // 创建Session
        Session sess = sf.openSession();
        // 开始事务
        Transaction tx = sess.beginTransaction();

        /*List<Customer> list = sess.createQuery("SELECT c FROM Customer c", Customer.class)
                .getResultList();

        System.out.println(list);*/
        //这里的参数为?1
        String hql = "FROM Customer where custId = ?1";

        List<Customer> resultList = sess.createQuery(hql, Customer.class)
                .setParameter(1, 1L)
                .getResultList();

        System.out.println(resultList.get(0).toString());

        //也可以为:id  跟上边?1是一样的
        String hql1 = "FROM Customer where custId = :id";

        List<Customer> resultList1 = sess.createQuery(hql1, Customer.class)
                .setParameter("id", 1L)
                .getResultList();

        System.out.println(resultList.get(0).toString());
        // 提交事务
        tx.commit();
        // 关闭Session
        sess.close();
        sf.close();
    }


    @Test
    public void testR_HQL_single() {
        // 创建Session
        Session sess = sf.openSession();
        // 开始事务
        Transaction tx = sess.beginTransaction();

        Customer customer = sess.createQuery("SELECT c FROM Customer c where c.custId=:id", Customer.class)
                .setParameter("id", 1L)
                .getSingleResult();

        System.out.println(customer);
        // 提交事务
        tx.commit();
        // 关闭Session
        sess.close();
        sf.close();
    }

    @Test
    public void testU() {
        // 创建Session
        Session sess = sf.openSession();
        // 开始事务
        Transaction tx = sess.beginTransaction();

        Customer customer = new Customer();
        //有id 就修改 没有id 直接添加
        customer.setCustId(1L);
        customer.setCustAddress("123456");

        sess.update(customer);

        System.out.println(customer);
        // 提交事务
        tx.commit();
        // 关闭Session
        sess.close();
        sf.close();
    }


    @Test
    public void testU_HQL() {
        // 创建Session
        Session sess = sf.openSession();
        // 开始事务
        Transaction tx = sess.beginTransaction();

        String sql = "Update Customer set custName=:custName where custId=:id";
        sess.createQuery(sql)
                .setParameter("custName", "徐庶")
                .setParameter("id", 1L)
                .executeUpdate();
        // 提交事务
        tx.commit();
        // 关闭Session
        sess.close();
        sf.close();
    }


    @Test
    public void testD() {
        // 创建Session
        Session sess = sf.openSession();
        // 开始事务
        Transaction tx = sess.beginTransaction();

        Customer customer = new Customer();
        customer.setCustId(4L);
        sess.delete(customer);
        // 提交事务
        tx.commit();
        // 关闭Session
        sess.close();
        sf.close();
    }

    @Test
    public void testD_HQL() {
        // 创建Session
        Session sess = sf.openSession();
        // 开始事务
        Transaction tx = sess.beginTransaction();

        String sql = "DELETE FROM Customer WHERE custId=:id";
        sess.createQuery(sql)
                .setParameter("id", 1L)
                .executeUpdate();
        // 提交事务
        tx.commit();
        // 关闭Session
        sess.close();
        sf.close();
    }

}
如果单独使用hibernate的API来进行持久化操作,则不能随意切换其他ORM框架
Jpa示例
1.添加META-INF\persistence.xml(在resource下添加)

<?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>
        <!--需要进行ORM的POJO类-->
        <class>com.wzh.pojo.Customer</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="123456"/>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/springdata_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>
测试
package com.wzh;

import com.wzh.pojo.Customer;
import org.hibernate.internal.SessionFactoryImpl;
import org.junit.Before;
import org.junit.Test;

import javax.persistence.*;
import java.util.List;

/**
 * @ProjectName: springDataJpa-demo
 * @Package: com.wzh
 * @ClassName: JpaTest
 * @Author: 王振华
 * @Description:
 */
public class JpaTest {

    private EntityManagerFactory factory;
    EntityManager em;

    @Before
    public void bofore() {
        //1.加载配置文件,创建entityManagerFactory new Configuration.buildSessionFactory();
        factory = Persistence.createEntityManagerFactory("hibernateJPA");
        // 2. 获取entityManager对象 sessionFactory.openSession();
        em = factory.createEntityManager();
    }

    /**
    * 添加
    */
    @Test
    public void testC() {
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        Customer customer = new Customer();
        customer.setCustName("里斯");
        customer.setCustAddress("北京");

        em.persist(customer);

        tx.commit();
    }

    /**
     * 查询全部
     * 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 Customer c";
        Query query = em.createQuery(jpql);//创建Query查询对象,query对象才是执行jqpl的对象

        //发送查询,并封装结果集
        List list = query.getResultList();

        for (Object obj : list) {
            System.out.print(obj);
        }

        //4.提交事务
        tx.commit();
        //5.释放资源
        em.close();
    }

    @Test
    public void testR() {
        //2.开启事务
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Customer customer = em.getReference(Customer.class, 1L);
        System.out.println("===========================");
        System.out.println(customer);
        //4.提交事务
        tx.commit();
        //5.释放资源
        em.close();
    }

}

如果想切换为别的ORM框架 比如open jpa

1.加入依赖

        <!--openjpa-->
        <dependency>
            <groupId>org.apache.openjpa</groupId>
            <artifactId>openjpa-all</artifactId>
            <version>3.2.0</version>
        </dependency>

2.persistence.xml添加一个新的jpa实现

<?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>
        <!--需要进行ORM的POJO类-->
        <class>com.wzh.pojo.Customer</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="123456"/>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/springdata_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>

    <!--openjpa-->
    <persistence-unit name="openJPA" transaction-type="RESOURCE_LOCAL">

        <!--jpa的实现方式 -->
        <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
        <!--需要进行ORM的POJO类-->
        <class>com.wzh.pojo.Customer</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="123456"/>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/springdata_jpa?
serverTimezone=UTC"/>

            <!--配置jpa实现方(hibernate)的配置信息
            可以自动生成数据库表 -->
            <property name="openjpa.jdbc.SynchronizedMappings" value="buildSchema(ForeignKeys=true)"/>

        </properties>
    </persistence-unit>
</persistence>

 测试

package com.wzh;

import com.wzh.pojo.Customer;
import org.hibernate.internal.SessionFactoryImpl;
import org.junit.Before;
import org.junit.Test;

import javax.persistence.*;
import java.util.List;

/**
 * @ProjectName: springDataJpa-demo
 * @Package: com.wzh
 * @ClassName: JpaTest
 * @Author: 王振华
 * @Description:
 */
public class JpaTest {

    private EntityManagerFactory factory;
    EntityManager em;

    @Before
    public void bofore() {
        //1.加载配置文件,创建entityManagerFactory new Configuration.buildSessionFactory();
        factory = Persistence.createEntityManagerFactory("hibernateJPA");
        // 2. 获取entityManager对象 sessionFactory.openSession();
        em = factory.createEntityManager();
    }

    /**
    * 添加
    */
    @Test
    public void testC() {
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        Customer customer = new Customer();
        customer.setCustName("里斯");
        customer.setCustAddress("北京");

        em.persist(customer);

        tx.commit();
    }

    //立即查询
    @Test
    public void testR1() {
        //2.开启事务
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Customer customer = em.find(Customer.class, 1L);
        System.out.println("===========================");
        System.out.println(customer);
        //4.提交事务
        tx.commit();
        //5.释放资源
        em.close();
    }

    //延迟查询
    @Test
    public void testR() {
        //2.开启事务
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Customer customer = em.getReference(Customer.class, 1L);
        System.out.println("===========================");
        System.out.println(customer);
        //4.提交事务
        tx.commit();
        //5.释放资源
        em.close();
    }

    //修改
    @Test
    public void testU() {
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        Customer customer = new Customer();
        /*如果指定了主键:
             更新: 1.先查询 看是否有变化
                如果有变化  更新 如果没有变化就不更新
        如果没有指定主键:
             插入*/
        customer.setCustId(1L);
        customer.setCustName("王五");
        customer.setCustAddress("南京");

        em.merge(customer);

        tx.commit();
    }

    //删除
    @Test
    public void testD() {
        //2.开启事务
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        //必须是持久化状态的才能删除(也就是必须是数据库查出来的)  目前是游离状态的  或者用sql删除
        //java.lang.IllegalArgumentException: Removing a detached instance com.wzh.pojo.Customer#1
        /*Customer customer = new Customer();
        customer.setCustId(1L);
        em.remove(customer);*/

        Customer customer = em.find(Customer.class, 1L);
        em.remove(customer);

        //4.提交事务
        tx.commit();
        //5.释放资源
        em.close();
    }

    /**
     * 查询全部
     * 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 Customer c where custName=:name";
        Query query = em.createQuery(jpql);//创建Query查询对象,query对象才是执行jqpl的对象

        //发送查询,并封装结果集
        List list = query
                .setParameter("name","王五") //要跟:name  一致
                .getResultList();

        for (Object obj : list) {
            System.out.print(obj);
        }

        //4.提交事务
        tx.commit();
        //5.释放资源
        em.close();
    }


    /**
     * 跟据id修改   还是可以用sql的
     */
    @Test
    public void testU_SQL() {
        //2.开启事务
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        //3.查询全部
        String sql = "update tal_customer set cust_address = :address where cust_id = :id";
        em.createNativeQuery(sql)
                .setParameter("address","商丘")
                .setParameter("id",1L)
                .executeUpdate();

        //4.提交事务
        tx.commit();
        //5.释放资源
        em.close();
    }

}

jpa的对象4种状态

  • 临时状态:刚创建出来,∙没有与entityManager发生关系,没有被持久化,不处于entityManager中的对象
  • 持久状态:∙与entityManager发生关系,已经被持久化,您可以把持久化状态当做实实在在的数据库记录。
  • 删除状态:执行remove方法,事物提交之前
  • 游离状态:游离状态就是提交到数据库后,事务commit后实体的状态,因为事务已经提交了,此时实体的属 性任你如何改变,也不会同步到数据库,因为游离是没人管的孩子,不在持久化上下文中。

  • public void persist(Object entity) 

persist方法可以将实例转换为managed(托管)状态。在调用flush()方法或提交事物后,实例将会被插入到数据库中。

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

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

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

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

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

  • public void merge(Object entity)

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

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

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

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

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

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

  • public void refresh(Object entity)

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

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

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

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

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

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

  • public void remove(Object entity)

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

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

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

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

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

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

Spring data JPA

介绍

官网:https://spring.io/projects/spring-data-jpa#overview

 Spring Data JPA, part of the larger Spring Data family, makes it easy to easily implement JPA based repositories. This module deals with enhanced support for JPA based data access layers. It makes it easier to build Spring-powered applications that use data access technologies.

Implementing a data access layer of an application has been cumbersome for quite a while. Too much boilerplate code has to be written to execute simple queries as well as perform pagination, and auditing. Spring Data JPA aims to significantly improve the implementation of data access layers by reducing the effort to the amount that’s actually needed. As a developer you write your repository interfaces, including custom finder methods, and Spring will provide the implementation automatically.

Spring Data JPA 是更大的 Spring Data 系列的一部分,可以轻松实现基于 JPA 的repositories。该模块处理对基于 JPA 的数据访 问层的增强支持。它使构建使用数据访问技术的 Spring 驱动的应用程序变得更加容易。

实现应用程序的数据访问层已经很麻烦了。必须编写太多样板代码来执行简单的查询以及执行分页和审计。Spring Data JPA 旨在改 进数据访问层的实现以提升开发效率。作为开发人员,您编写存储库接口,包括自定义 finder 方法,Spring 将自动提供实现。

人话

spirng data jpa是spring提供的一套简化JPA开发的框架,按照约定好的规则进行【方法命名】去写dao层接口,就可以 在不写接口实现的情况下,实现对数据库的访问和操作。同时提供了很多除了CRUD之外的功能,如分页、排序、复杂查 询等等。

Spring Data JPA 让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它来实现,在实际的工作工程中,推荐使 用Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的ORM框架时提供了极大的方便,同时也使 数据库层操作更加简单,方便解耦

特性

SpringData Jpa 极大简化了数据库访问层代码。 如何简化的呢? 使用了SpringDataJpa,我们的dao层中只需要写接 口,就自动具有了增删改查、分页查询等方法。 

Spring Data JPA实例 

我们来实现一个基于Spring Data JPA的示例感受一下和之前单独使用的区别:

依赖

1.最好在父maven项目中设置spring data统一版本管理依赖: 因为不同的spring data子项目发布时间版本不一样,你自 己维护很麻烦, 这样不同的spring data子项目能保证是统一版本.

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Data Jpa 的相关文章

随机推荐

  • 服务计算--简单 web 服务与客户端开发实战

    一 概述 利用 web 客户端调用远端服务是服务开发本实验的重要内容 其中 要点建立 API First 的开发理念 实现前后端分离 使得团队协作变得更有效率 任务目标 选择合适的 API 风格 实现从接口或资源 领域 建模 到 API 设
  • C++ 字符串

    C 提供了以下两种类型的字符串表示形式 C 风格字符串 C 引入的 string 类类型 C 风格字符串 C 风格的字符串起源于 C 语言 并在 C 中继续得到支持 字符串实际上是使用 null 字符 终止的一维字符数组 因此 一个以 nu
  • 错误处理-mmdetection-AttributeError: ‘ConfigDict‘ object has no attribute ‘log_level‘

    第一次用商汤的mmdetection 遇到很多错误 mmdetection中网络的配置文件缺东西 至少缺了log level参数的值 此文章将继续更新我在使用过程中的问题与解决办法 敬请期待 祝你学习愉快 1 2 3 4 5 6 7 8 9
  • 数据库常用的四种方法

    排序查询 select 列表属性 列表属性 from 列表名order by 列表属性 列表属性 删除 delete from 列表名 where 列表属性 值 插入 insert into 列表名 values 值 值 值 值 inser
  • 数学知识整理:二重积分

    1 二重积分的性质 1 1 f x y 在有界闭区域上可积的充分条件 必要条件 在有界闭区域D上可积的函数f x y 必然是D上的有界函数 有界闭区域D上的连续函数或者分片连续函数f x y 在D上可积 1 2 线性性质 1 3 积分区域可
  • TCP/IP详解 卷1:协议 学习笔记 第十章 动态选路协议

    静态选路包括在配置接口时 以默认方式生成路由表项 对于直连路由 直连路由是由链路层协议发现的 一般指去往路由器的接口地址所在网段的路径 通过route命令增加表项 通常通过系统自引导程序文件 或通过ICMP重定向生成路由表项 通常在默认方式
  • 代理简介

    1 正向代理 正向代理类似一个跳板机 代理访问外部资源 比如我是一个用户 我访问不了某网站 但是我能访问一个代理服务器 这个代理服务器呢 他能访问那个我不能访问的网站 于是我先连上代理服务器 告诉他我需要那个无法访问网站的内容 代理服务器去
  • eclipse开发burpsuite插件

    安装相关软件 eclipse jee 2019 06 R win32 x86 64 zip burpsuite community edition v1 7 32 burpsuite 插件helloworld demo 下载链接在文章末尾
  • PyQt5之信号与信号槽

    一 信号与信号槽特点 PyQt的窗口控件类中有很多内置信号 开发者也可以添加自定义信号 信号与槽具有如下特点 一个信号可以连接多个槽 一个信号可以连接另一个信号 信号参数可以是任何Python类型 一个槽可以监听多个信号 信号与槽的连接方式
  • 定时删除centos服务器日志

    现在java程序的日志一般是使用log4j slf4j 来打日志 并且一般都喜欢用DailyRollingFileAppender模式 就是每天产生一个日志 还有一种是 RollingFileAppender模式 这个模式是按文件大小来保存
  • QT 实现五子棋

    1 程序简介 五子棋是一款大家都熟系的小游戏 这里给大家一步一步的详细介绍如何用QT开发这个游戏 并通过这款游戏的开发练习 进一步熟系 qvector qpoint qpainter QMouseEvent 产生工具栏等的用法和方法 2 程
  • 小学生报编程机器人有什么益处

    小学生报编程机器人有什么益处 小孩子的学习一直都是很多家长们非常关心和重视的一件事情 很多的家长在培养孩子的学习方面也可以说是相当的耐心的 就拿现在很多的家长想要孩子去学习机器人编程的课程来说 有的家长对于孩子学习机器人编程的好处并不是很清
  • 信号集(未决信号集,阻塞信号集)

    未决信号集和阻塞信号集的关系 阻塞信号集是当前进程要阻塞的信号的集合 未决信号集是当前进程中还处于未决状态的信号的集合 这两个集合存储在内核的PCB中 下面以SIGINT为例说明信号未决信号集和阻塞信号集的关系 当进程收到一个SIGINT信
  • 《从零开始编写一个直播服务器》 C++ 实现一个最简单的RTSP流媒体服务器

    流媒体开发系列文章 文章目录 流媒体开发系列文章 前言 一 rtsp流是什么 二 使用步骤 1 服务器代码 总结 前言 在安防行业中 onvif协议与gb协议是两种标准 gb是国内安防行业的标准 onvif是国外的安防行业的标准 其中gb2
  • 【华为OD机试】数字游戏【2023 B卷

    华为OD机试 真题 点这里 华为OD机试 真题考点分类 点这里 题目描述 小明玩一个游戏 系统发1 n张牌 每张牌上有一个整数 第一张给小明 后n张按照发牌顺序排成连续的一行 需要小明判断 后n张牌中 是否存在连续的若干张牌 其和可以整除小
  • Heroku 部署有关 opencv 的 Django 后端应用(pdf2docx)

    文章目录 场景 解决方案 Aptfile Buildpacks Dashboard 上手动构建 Heroku CLI 终端构建 Requirements txt 提交改变 场景 我使用 heroku 部署了一个 Django 后端项目 里面
  • C/C++内存布局

    下图是c c 的进程的内存分布布局图 搞清楚内存布局对于理解一个程序是非常重要的 一个程序运行起来 操作系统会给每个进程分配一个 4G 的程序地址空间 当然这都是虚拟地址空间 因为如果一个进程分 4G 的内存 那么就算有再多的内存也不够分
  • windows下的另一个辅助工具Devcon.exe(用会了绝对是神器)

    Device Console Help devcon exe r m
  • Unity3D关于iTween回调函数

    ITween一共三个回调函数 onstart onupdate和oncomplete 顾名思义可以从名字中看出来 常用到最后一个 要是我以后项目中用到了前两个函数 我会把例子添加上 关于oncomplete 就是在itween移动完成以后所
  • Spring Data Jpa

    spring data介绍 Spring Data s mission is to provide a familiar and consistent Spring based programming model for data acce