SpringDataJpa学习记录-----01什么是JPA

一、为什么要用Spring Data

将不同的数据存储进行了统一,提升了开发效率,降低了学习成本;针对不同的数据库提供不同的模板对象,通过模板对象来操作对应的数据库。

在这里插入图片描述

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

对于每种持久性存储,通常需要为不同存储库提供对不同CRUD持久化操作。Spring Data为这些持久性存储以及特定实现提供了通用接口(CrudRepository、Paging(分页)AndSorting(排序)Repository)和模板(jdbcTemplate、redisTemplate、RestTemplate、MongoTemplate)。

目的是统一和简化对不同类型持久性存储的访问。

二、JPA

什么是JPA?

相同处:

  1. JPA是JDBC的升级版
  2. JDBC和JPA都是一组规范接口

不同处:

  1. JDBC是由各个关系型数据库实现的,JPA是由ORM框架实现

    ORM:表与java类的映射关系

  2. JDBC使用SQL语句和数据库通信,JPA用面向对象方式,通过ORM框架来生成SQL,进行操作

  3. JPA在JDBC之上的,JPA要依赖JDBC才能操作数据库

JPA是Sun官方提出的一种ORM规范。

Hibernate与JPA:

JPA仅仅是一种规范,也就是说JPA仅仅定义了一些接口,而接口是需要实现才能工作的。

Hibernate就是实现了JPA接口的ORM框架。

总结:JPA是一套ORM规范,HIbernate实现了JPA规范!

Hibernate与Mybatis:

Mybaits:

  1. 需要自己写sql语句,半自动的ORM框架
  2. 是jdbc的封装
  3. 在业务比较复杂系统进行使用

Hibernate:

  1. 面向对象,全自动的ORM框架
  2. 根据ORM映射生成不同SQL
  3. 在业务相对简单的系统进行使用,随着微服务的流行

三、Hibernate的使用

依赖导入:

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-entitymanager</artifactId>
    <version>5.6.15.Final</version>
</dependency>
    
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
    <version>5.1.22</version>
</dependency>

注解:

@Entity // 作为Hibernate 实体类
@Table(name = "tb_xxxx") // 映射的表名
@Id // 声明主键的配置
@GeneratedValue(strategy = GenerationType.xxx) // 配置主键的生成策略
	/**
	 * GenerationType.IDENTITY:自增,mysql
	 * GenerationType.SEQUENCE:序列,oracle
	 * GenerationType.TABLE:jap提供的一种机制,通过一张数据库表的形式帮助我们完成
	 * GenerationType.AUTO:由程序自动的帮助我们选择主键生成策略
	 */
@Column(name = "cus_id") // 配置属性和字段的映射关系

hibernate.cfg.xml配置:

<?xml version="1.0" encoding="UTF‐8"?>
<!DOCTYPE hibernate‐configuration PUBLIC
"‐//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate‐configuration‐3.0.dtd">
<hibernate-configuration>
    <!-- 通常,一个session-factory节点代表一个数据库 -->
    <session-factory>
        <!-- 配置数据库连接信息 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/xxx</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
        
        <!-- 在日志中显示hibernate运行时候执行的sql语句 默认false-->
        <property name="hibernate.show_sql">true</property>
        <!-- 格式化sql 默认false-->
        <property name="hibernate.format_sql">true</property>
        <!-- 表生成策略
  			默认none 不自动生成
  			update   如果没有表会创建,有会检查更新
		    create	 创建-->
        <property name="hibernate.hbm2ddl.auto">create</property>
        <!--根据不同的方言生成符合当前数据库语法的sql-->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        
        <!--加载映射(通过xml映射)-->
        <mapping resource="zhongfucheng/domain/User.hbm.xml"/>
        <!--加载映射(通过注解映射)-->
        <mapping class="com.xxx.pojo.xxx"></mapping>

    </session-factory>
</hibernate-configuration>

方法测试:

public class HibernateTest {

    // Session工厂  Session:数据库会话  代码和数据库的一个桥梁
    private SessionFactory sf;

    @Before
    public void init() {
        StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure("/hibernate.cfg.xml").build();
        //根据服务注册类创建一个元数据资源集,同时构建元数据并生成应用一般唯一的的session工厂
        sf = new MetadataSources(registry).buildMetadata().buildSessionFactory();
    }

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

            // 创建实例
            Customer customer = new Customer();
            customer.setCustName("TT");
            // 插入
            session.save(customer);

            // 提交事务
            tx.commit();
        }
    }


    @Test
    public void testR(){
        try(Session session = sf.openSession()){
            Transaction tx = session.beginTransaction();

            // 立即查询
            Customer customer = session.find(Customer.class, 1L);
            System.out.println("=====================");
            System.out.println(customer);

            tx.commit();
        }
    }


    @Test
    public void testR_lazy(){
        try(Session session = sf.openSession()){
            Transaction tx = session.beginTransaction();

            // 懒加载,会在调用改实例时才去查询
            Customer customer = session.load(Customer.class, 1L);
            System.out.println("=====================");
            System.out.println(customer);

            tx.commit();
        }
    }


    @Test
    public void testU(){
        try(Session session = sf.openSession()){
            Transaction tx = session.beginTransaction();

            Customer customer = new Customer();
            customer.setCustId(1L);
            customer.setCustName("TT");
            // 更新
            session.update(customer);

            tx.commit();
        }

    }


    @Test
    public void testD(){
        try(Session session = sf.openSession()){
            Transaction tx = session.beginTransaction();

            Customer customer = new Customer();
            customer.setCustId(2L);
            // 删除
            session.remove(customer);

            tx.commit();
        }
    }


    @Test
    public void testR_HQL(){
        try(Session session = sf.openSession()){
            Transaction tx = session.beginTransaction();

            // 这里可以不用写select Customer为实例类名,不是表名;custId为实例类属性,不是表字段
            String hql=" FROM Customer where custId=:id";
            List<Customer> resultList = session.createQuery(hql, Customer.class)
                    //设置hql中的id值
                    .setParameter("id",1L)
                    // 执行查询并返回结果集
                    .getResultList();
            System.out.println(resultList);
            
            tx.commit();
        }
    }
}

注:如果单独使用hibernate的API来进行持久化操作,则不能随意切换其他ORM框架

四、JPA规范的使用

xml配置:

添加META-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的实现方式,可以有多种实现方式,比如hibernate、openjpa等 ‐‐>
		<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
         <!‐‐ 需要进行ORM的POJO类 ‐‐>
		<class>com.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="root"/>
			<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(默认false)
				自动创建数据库表  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>

方法测试

public class JpaTest {

    //相当于hibernate中的SessionFactory
    EntityManagerFactory factory;

    @Before
    public void before(){
         factory= Persistence.createEntityManagerFactory("hibernateJPA");
    }

    @Test
    public void testC(){
        //相当于hibernate中的Session
        EntityManager em = factory.createEntityManager();
        //开启事务
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Customer customer = new Customer();
        customer.setCustName("张三");
        //插入操作
        em.persist(customer);

        //提交事务
        tx.commit();
    }

    // 立即查询
    @Test
    public void testR(){
        EntityManager em = factory.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Customer customer = em.find(Customer.class, 1L);
        System.out.println("========================");
        System.out.println(customer);

        tx.commit();
    }


    // 延迟查询
    @Test
    public void testR_lazy(){
        EntityManager em = factory.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Customer customer = em.getReference(Customer.class, 1L);
        System.out.println("========================");
        System.out.println(customer);

        tx.commit();
    }


    @Test
    public void testU(){
        EntityManager em = factory.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Customer customer = new Customer();
        customer.setCustId(5L);
        customer.setCustName("王五");

        /*
        * 如果指定了主键:
        * 更新: 先查询  看是否有变化
        *           如果有变化 更新
        *           如果没有变化就不更新
        *       如果没有指定了主键:
        *          插入
        */
        em.merge(customer);

        tx.commit();
    }

    @Test
    public void testU_JPQL(){
        EntityManager em = factory.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        //使用jpql语句来更新数据
        String jpql="UPDATE Customer set custName=:name where custId=:id";
        em.createQuery(jpql)
                .setParameter("name","李四")
                .setParameter("id",5L)
                        .executeUpdate();

        tx.commit();
    }


    @Test
    public void testU_SQL(){
        EntityManager em = factory.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        //使用sql语句来更新数据
        String sql="UPDATE tb_customer set cust_name=:name where id=:id";
        em.createNativeQuery(sql)
                .setParameter("name","王五")
                .setParameter("id",5L)
                .executeUpdate();

        tx.commit();
    }


    @Test
    public void testD(){
        EntityManager em = factory.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Customer customer = em.find(Customer.class,5L);
        //如果这里的customer是new出来的,customer将会处于游离状态,删除操作会产生异常,
        em.remove(customer);

        tx.commit();
    }
}

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状态的实体,该方法将会抛出异常。
      ​​​​​​
  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TT_aee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值