SpringData JPA第一章

一、ORM思想

主要目的:操作实体类就相当于操作数据库表
需要建立两个映射关系:
①实体类和表的映射关系
②实体类中属性和表中字段的关系

实现了ORM思想的框架:mybatis、hibernate

二、hibernate框架介绍

:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO(Java实体类对象)与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。

三、JPA规范

:JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。是SUN公司推出的一款基于ORM的规范,内部是由一系列的接口和抽象类构成。

JPA的优势

标准化

JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。

容器级特性的支持

JPA框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。

简单方便

JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易地掌握。JPA基于非侵入式原则设计,因此可以很容易地和其它框架或者容器集成。

查询能力

JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。

高级特性

JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。

四、JPA的基本操作

1.搭建环境的过程

①创建maven工程,导入坐标

资料来自bill bill用户:Cappuccinoべ

<dependencies>

       <!-- junit -->
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>4.12</version>
           <scope>test</scope>
       </dependency>

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

       <!-- c3p0 -->
       <dependency>
           <groupId>org.hibernate</groupId>
           <artifactId>hibernate-c3p0</artifactId>
           <version>6.0.0.Alpha8</version>
       </dependency>

       <!-- log日志 -->
       <dependency>
           <groupId>log4j</groupId>
           <artifactId>log4j</artifactId>
           <version>1.2.17</version>
       </dependency>

       <!-- Mysql and MariaDB -->
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>8.0.22</version>
       </dependency>

   </dependencies>

②配置JPA的核心配置文件

位置:配置到类路径下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="myjpa" transaction-type="RESOURCE_LOCAL">
       <!--jpa的实现方式-->
       ><provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

       <properties>
           <!--数据库信息
                   mysql方言:org.hibernate.dialect.MySQLDialect
                   用户名:javax.persistence.jdbc.user
                   密码:javax.persistence.jdbc.password
                   驱动:javax.persistence.jdbc.driver
                   数据库地址:javax.persistence.jdbc.url
           -->
           <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
           <property name="javax.persistence.jdbc.user" value="root"/>
           <property name="javax.persistence.jdbc.password" value="abc1234."/>
           <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
           <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa?useSSl=false&amp;requireSSL=false&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai"/>

           <!--(可选的配置)配置jpa实现方的配置信息
               显示sql,false/true
               自动创建数据库表,
                   create:程序运行时创建数据库表(如果有表,先删除再创建)
                   update:程序运行时创建表(如果有表不会创建表)
                   none:不会创建表
           -->
           <property name="hibernate.show_sql" value="true"/>
           <property name="hibernate.hbm2ddl.auto" value="create"/>
       </properties>
   </persistence-unit>
</persistence>

③编写客户实体类

配置映射关系
1.实体类和表的映射关
@Entity:声明此类是实体类
@Table:配置实体类中的映射关系
name:配置数据库表的名称
2.实体类中属性和表中

package cn.Itcast.domain;

/*
*   客户实体类
* */
public class Customer {
   private Long custId;//客户主键
   private String custName;//客户名称
   private String custSource;//客户来源
   private String custLevel;//客户级别
   private String custIndustry;//客户所属行业
   private String custPhone;//客户的联系方式
   private String custAddress;//客户地址
   //省略setter、getter和toString方法
}

④配置实体类和表、类中属性和表中字段的映射关系(重要)

客户实体类
配置映射关系
1.实体类和表的映射关系
@Entity:声明此类是实体类
@Table:配置实体类中的映射关系
name:配置数据库表的名称
2.实体类中属性和表中字段的映射关系
@Id:声明主键的配置
@GeneratedValue:配置主键的生成策略
GenerationType.IDENTITY:自增(底层数据库必须支持自增,如mysql)
GenerationType.SEQUENCE:序列(底层数据库必须支持序,如Oracle)
GenerationType.TABLE:jpa提供的一种机制,通过一张数据库表的形式完成主键自增
GenerationType.AUTO:程序自动的帮助我们选择主键生成策略
@Column:配置属性和字段的映射关系
name:数据库表中字段的名称

package cn.Itcast.domain;

import javax.persistence.*;

@Entity
@Table(name = "cst_customer")
public class Customer {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "cust_id")
   private Long custId;//客户主键
   @Column(name = "cust_name")
   private String custName;//客户名称
   @Column(name = "cust_source")
   private String custSource;//客户来源
   @Column(name = "cust_level")
   private String custLevel;//客户级别
   @Column(name = "cust_industry")
   private String custIndustry;//客户所属行业
   @Column(name = "cust_phone")
   private String custPhone;//客户的联系方式
   @Column(name = "cust_address")
   private String custAddress;//客户地址
   //省略setter、getter和toString方法
}

⑤保存客户到数据库中

JPA的操作步骤:
1.加载配置文件创工厂(实体管理类工厂)对象
2.通过实体管理类工厂获取实体管理器
3.获取事务对象,开启事务
4.完成增删改查
5.提交事务(回滚事务)
6.释放资源

package cn.Itcast.test;

import cn.Itcast.domain.Customer;
import org.junit.Test;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class JpaTest {
   @Test
   public void testSave(){
       /*1.加载配置文件创工厂(实体管理类工厂)对象*/
       EntityManagerFactory factory= Persistence.createEntityManagerFactory("myJpa");
       /*2.通过实体管理类工厂获取实体管理器*/
       EntityManager em=factory.createEntityManager();
       /*3.获取事务对象,开启事务*/
       EntityTransaction tx=em.getTransaction();//获取事务对象
       tx.begin();//开启事务
       /*4.完成增删改查*/
       Customer customer=new Customer();
       customer.setCustName("传智播客");
       customer.setCustIndustry("教育");
       em.persist(customer);//保存操作
       /*5.提交事务(回滚事务)*/
       tx.commit();
       /*6.释放资源*/
       em.close();
       factory.close();
   }
}

输出结果:
Hibernate: drop table if exists cst_customer
Hibernate: create table cst_customer (cust_id bigint not null auto_increment, cust_address varchar(255), cust_industry varchar(255), cust_level varchar(255), cust_name varchar(255), cust_phone varchar(255), cust_source varchar(255), primary key (cust_id)) engine=InnoDB
Hibernate: insert into cst_customer (cust_address, cust_industry, cust_level, cust_name, cust_phone, cust_source) values (?, ?, ?, ?, ?, ?)

2.完成基本的CRUD案例(增删改查)

工具类
解决实体管理器工厂的浪费资源和耗时问题:
通过静态代码块的形式,当程序第一次访问此工具类时,
创建一个公共的实体管理器工厂对象。

流程:
第一次访问getEntityManager方法:经过静态代码块创建一个factory对象,再调用EntityManager对象。
第二次访问getEntityManager方法:直接通过一个已经创建好的factory对象,调用EntityManager对象。

package cn.Itcast.utils;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class JpaUtils {
   private static EntityManagerFactory factory;
   static {
       /*1.加载配置文件创工厂(实体管理类工厂)对象*/
       factory=Persistence.createEntityManagerFactory("myjpa");
   }

   /*获取EntityManager对象*/
   public static EntityManager getEntityManager(){
       return factory.createEntityManager();
   }
}
public class JpaTest {
   @Test
   public void testSave(){
       //通过工具类获取EntityManager 对象
       EntityManager em= JpaUtils.getEntityManager();
       /*3.获取事务对象,开启事务*/
       EntityTransaction tx=em.getTransaction();//获取事务对象
       tx.begin();//开启事务
       /*4.完成增删改查*/
       Customer customer=new Customer();
       customer.setCustName("传智播客");
       customer.setCustIndustry("教育");
       em.persist(customer);//保存操作
       /*5.提交事务(回滚事务)*/
       tx.commit();
       /*6.释放资源*/
       em.close();
   }
}

find():根据id查询数据 //立即加载
1.查询的对象就是当前客户对象本身
2.在调用find方法的时候,就会发送sql语句查询数据库

class属性:查询数据的结果需要包装的实体类类型的字节码
id属性:查询到主键的取值

   /*
       根据id查询客户
   */
   @Test
   public void testFind(){
       //1.通过工具类获取EntityManager对象
       EntityManager entityManager=JpaUtils.getEntityManager();
       //2.开启事务
       EntityTransaction tx=entityManager.getTransaction();//获取事务对象
       tx.begin();//开启事务
       //3.增删改查
           /*
               find:根据id查询数据
                   class:查询数据的结果需要包装的实体类类型的字节码
                   id:查询到主键的取值
           */
       Customer customer=entityManager.find(Customer.class,1l);
       System.out.println(customer);
       //4.提交事务
       tx.commit();
       //5.释放资源
       entityManager.close();
   }

getReference():根据id查询客户//延迟加载(懒加载)
1.获取的对象是一个动态代理对象
2.调用getReference不会立即发送sql语句查询数据
当调用查询结果对象的时候,才会发送查询的sql语句,
即什么时候用什么时候发送sql语句查询数据库

class属性:查询数据的结果需要包装的实体类类型的字节码
id属性:查询到主键的取值

   @Test
   public void testReference(){
       //1.通过工具类获取EntityManager对象
       EntityManager entityManager=JpaUtils.getEntityManager();
       //2.开启事务
       EntityTransaction tx=entityManager.getTransaction();//获取事务对象
       tx.begin();//开启事务
       //3.增删改查
       Customer customer=entityManager.getReference(Customer.class,1l);
       System.out.println(customer);
       //4.提交事务
       tx.commit();
       //5.释放资源
       entityManager.close();
   }

remove():根据id查询信息,再根据返回的对象删除信息

   @Test
   public void testRemove(){
       //1.通过工具类获取EntityManager对象
       EntityManager entityManager=JpaUtils.getEntityManager();
       //2.开启事务
       EntityTransaction tx=entityManager.getTransaction();//获取事务对象
       tx.begin();//开启事务
       //3.增删改查
       //根据id查询客户
       Customer customer=entityManager.getReference(Customer.class,1l);
       //再调用remove方法完成删除操作
       if (customer!=null){
           entityManager.remove(customer);
       }
       //4.提交事务
       tx.commit();
       //5.释放资源
       entityManager.close();
   }

merge():用于在使用setter方法更新数据后,发送更新
属性T:传入已更新数据的对象

   @Test
   public void testUpdate(){
       //1.通过工具类获取EntityManager对象
       EntityManager entityManager=JpaUtils.getEntityManager();
       //2.开启事务
       EntityTransaction tx=entityManager.getTransaction();//获取事务对象
       tx.begin();//开启事务
       //3.增删改查
       //根据id查询客户
       Customer customer=entityManager.getReference(Customer.class,2l);
       //再将更新客户
       customer.setCustIndustry("it教育");
       //调用方法发送更新
       entityManager.merge(customer);
       //4.提交事务
       tx.commit();
       //5.释放资源
       entityManager.close();
   }

测试jpql查询
查询全部:
jpql:from 全限定名称;
sql:select * from 表名;

package cn.Itcast.test;

import cn.Itcast.domain.Customer;
import cn.Itcast.utils.JpaUtils;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import java.util.List;

public class JpqlTest {
   @Test
   public void testFindAll(){
       //1.通过工具类获取EntityManager对象
       EntityManager entityManager=JpaUtils.getEntityManager();
       //2.开启事务
       EntityTransaction tx=entityManager.getTransaction();//获取事务对象
       tx.begin();//开启事务
      //3.增删改查
       String jpql= "from cn.Itcast.domain.Customer";
       //创建Query查询对象,query对象才是执行jqpl的对象
       Query query=  entityManager.createQuery(jpql);
       //发送查询并封装结果集
       List list=query.getResultList();
       for (Object object:list){
           System.out.println(object);
       }
       //4.提交事务
       tx.commit();
       //5.释放资源
       entityManager.close();
   }
}

jpql排序查询:
根据id倒序查询全部:
jpql:from 全限定名称 order by 字段 desc;
sql:select * from 表名 order by 字段 desc;

   @Test
   public void testOrders(){
       //1.通过工具类获取EntityManager对象
       EntityManager entityManager=JpaUtils.getEntityManager();
       //2.开启事务
       EntityTransaction tx=entityManager.getTransaction();//获取事务对象
       tx.begin();//开启事务
       //3.增删改查
       String jpql= "from cn.Itcast.domain.Customer order by custId desc";
       //创建Query查询对象,query对象才是执行jqpl的对象
       Query query=  entityManager.createQuery(jpql);
       //发送查询并封装结果集
       List list=query.getResultList();
       for (Object object:list){
           System.out.println(object);
       }
       //4.提交事务
       tx.commit();
       //5.释放资源
       entityManager.close();
   }

jpql统计查询:
jpql:select COUNT(字段) from 全限定名称;
sql:select count(字段) from 表名;

   @Test
   public void testCount(){
       //1.通过工具类获取EntityManager对象
       EntityManager entityManager=JpaUtils.getEntityManager();
       //2.开启事务
       EntityTransaction tx=entityManager.getTransaction();//获取事务对象
       tx.begin();//开启事务
       //3.增删改查
       String jpql= "select COUNT(custId) from cn.Itcast.domain.Customer";
       //创建Query查询对象,query对象才是执行jqpl的对象
       Query query=  entityManager.createQuery(jpql);
      //发送查询并封装结果集
       /*
           getResultList:直接将查询结果封装为list集合
            getSingleResult:得到唯一的结果集
       */
       Object result=query.getSingleResult();
       System.out.println(result);
       //4.提交事务
       tx.commit();
       //5.释放资源
       entityManager.close();
   }

jpql分页查询:
jpql:from 全限定名称;
sql:select * from 表名 limit ?,?;

   @Test
   public void testPaged(){
       //1.通过工具类获取EntityManager对象
       EntityManager entityManager=JpaUtils.getEntityManager();
       //2.开启事务
       EntityTransaction tx=entityManager.getTransaction();//获取事务对象
       tx.begin();//开启事务
       //3.增删改查
       String jpql= "from cn.Itcast.domain.Customer";
       //创建Query查询对象,query对象才是执行jqpl的对象
       Query query=  entityManager.createQuery(jpql);
       //对分页参数赋值
       query.setFirstResult(1);//起始索引
       query.setMaxResults(2);//每页查询的条数
       //发送查询并封装结果集
       List list=query.getResultList();
       for (Object object:list){
           System.out.println(object);
       }
       //4.提交事务
       tx.commit();
       //5.释放资源
       entityManager.close();
   }

jpql条件查询:
查询以“传智播客”开头的客户
jpql:from 全限定名称 where 字段 like ?;
sql:select * from 表名 where 字段 like '传智播客%';

   @Test
   public void testCondition(){
       //1.通过工具类获取EntityManager对象
       EntityManager entityManager=JpaUtils.getEntityManager();
       //2.开启事务
       EntityTransaction tx=entityManager.getTransaction();//获取事务对象
       tx.begin();//开启事务
       //3.增删改查
       String jpql= "from cn.Itcast.domain.Customer where custName like ?1";
       //创建Query查询对象,query对象才是执行jqpl的对象
       Query query=  entityManager.createQuery(jpql);
       //对占位符参数赋值
       query.setParameter(1,"传智播客%");//第一个参数:占位符的索引位置;第二个参数:取值
       //发送查询并封装结果集
       List list=query.getResultList();
       for (Object object:list){
           System.out.println(object);
       }
       //4.提交事务
       tx.commit();
       //5.释放资源
       entityManager.close();
   }

笔记来源:bilibili「黑化肥发灰挥发会发飞

视频链接:https://www.bilibili.com/video/BV1Y4411W7Rx?from=search&seid=1015202159893666729&spm_id_from=333.337.0.0

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容

  • 环境搭建 导入依赖 maven3.6.3 5.2.5.RELEASE <hibernate.ve...
    BarryDeng阅读 1,374评论 0 0
  • 1 什么是JPA 1.1 JPA概念 JPA是Java Persistence API 的简称,中文名Java持久...
    王晶博阅读 435评论 0 0
  • 此处选用尚硅谷的教程和资料 http://www.atguigu.com/ 感谢其开源 JDBC JPA是什么 J...
    是小猪童鞋啦阅读 537评论 0 0
  • JPA 概述 Java Persistence API(Java 持久层 API):用于对象持久化的 API 作用...
    熊少文阅读 648评论 0 0
  • 本文章只是自己在学习中记的笔记(可能有点乱),只提供参考。如有错误请指出 什么是jpa JPA (Java Per...
    沃林阅读 324评论 0 0