SpringDataJPA(一):ORM思想和hibernate以及JPA的概述和基本操作

传统jdbc引出的问题:

主要目的:操作实体类就相当于操作数据库表

  • 建立两个映射关系:
    • 实体类和表的映射关系
    • 实体类中属性和表中字段的映射关系
  • 不再重点关注:sql语句

一、ORM概述

ORM(Object-Relational Mapping) 表示对象关系映射。在面向对象的软件开发中,通过ORM就可以把对象映射到关系型数据库中。只要有一套程序能够做到建立对象与数据库的关联,操作对象就可以直接操作数据库数据,就可以说这套程序实现了ORM对象关系映射。

简单的说:ORM就是建立实体类和数据库表之间的关系,从而达到操作实体类就相当于操作数据库表的目的。

1.1 为什么使用ORM

当实现一个应用程序时(不使用O/R Mapping),我们可能会写特别多数据访问层的代码,从数据库保存数据、修改数据、删除数据,而这些代码都是重复的。而使用ORM则会大大减少重复性代码。对象关系映射(Object Relational Mapping,简称ORM),主要实现程序对象到关系数据库数据的映射。

1.2 常见ORM框架

常见的orm框架:Mybatis(ibatis)、Hibernate、Jpa

二、hibernate与JPA的概述

2.1 hibernate概述

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

2.2 JPA概述

JPA的全称是Java Persistence API, 即Java 持久化API,是SUN公司推出的一套基于ORM的规范,内部是由一系列的接口和抽象类构成。

对比JDBC规范理解JPA:

JPA通过JDK 5.0注解描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

2.3 JPA的优势
1. 标准化

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

2. 容器级特性的支持

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

3. 简单方便

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

4. 查询能力

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

5. 高级特性

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

2.4 JPA与hibernate的关系

JPA规范本质上就是一种ORM规范,注意不是ORM

JPA和Hibernate的关系就像JDBC和JDBC驱动的关系,JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现。JPA怎么取代Hibernate呢?JDBC规范可以驱动底层数据库吗?答案是否定的,也就是说,如果使用JPA规范进行数据库操作,底层需要hibernate作为其实现类完成数据持久化工作。

三、JPA的入门案例、JPA中的主键生成策略

创建客户的数据库表:

/*创建客户表*/
CREATE TABLE cst_customer (cust_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',cust_name varchar(32) NOT NULL COMMENT '客户名称(公司名称)',cust_source varchar(32) DEFAULT NULL COMMENT '客户信息来源',cust_industry varchar(32) DEFAULT NULL COMMENT '客户所属行业',cust_level varchar(32) DEFAULT NULL COMMENT '客户级别',cust_address varchar(128) DEFAULT NULL COMMENT '客户联系地址',cust_phone varchar(64) DEFAULT NULL COMMENT '客户联系电话',PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

maven工程导入坐标:pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>top.onefine</groupId><artifactId>jpa_day1</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.hibernate.version>5.4.14.Final</project.hibernate.version></properties><dependencies><!-- https://mvnrepository.com/artifact/junit/junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope></dependency><!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager --><!-- hibernate对jpa的支持包 --><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-entitymanager</artifactId><version>${project.hibernate.version}</version></dependency><!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0 --><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-c3p0</artifactId><version>${project.hibernate.version}</version></dependency><!-- https://mvnrepository.com/artifact/log4j/log4j --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><!-- Mysql and MariaDB --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.19</version></dependency><!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><scope>provided</scope></dependency></dependencies>
</project>

配置JPA的核心配置文件:src/main/resources/META-INF/persistence.xml:

在java工程的src路径下创建一个名为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><!-- 数据库信息 --><property name="javax.persistence.jdbc.user" value="root"/><property name="javax.persistence.jdbc.password" value="963123"/><property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/><property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/study_eesy?serverTimezone=UTC"/><!-- 可选配置:配置JPA实现方(如这里是hibernate)的配置信息显示sql:hibernate.show_sqltrue/false自动创建数据库表:hibernate.hbm2ddl.autocreate  程序运行时创建数据库表(如果有表,删除后再创建)update  程序运行时创建数据库表(如果有表,不会创建表)none    不会创建表--><property name="hibernate.show_sql" value="true"/><property name="hibernate.hbm2ddl.auto" value="update"/></properties></persistence-unit>
</persistence>

创建客户的实体类,及编写实体类和数据库表的映射配置:src/main/java/top/onefine/domain/Customer.java:

注:所有的注解都是使用JPA的规范提供的注解,所以在导入注解包的时候,一定要导入javax.persistence下的。

package top.onefine.domain;import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;import javax.persistence.*;/*** 客户的实体类*      配置映射关系:*          1. 实体类和表的映射关系*              @Entity: 声明实体类*              @Table: 配置实体类和表的映射关系*                  name:配置数据库表的名称*          2. 实体类中属性和表中字段的映射关系*              @Id: 声明此属性是对应数据库表中的主键*              @GeneratedValue: 配置注解的生成策略*                  strategy: 策略*                      GenerationType.IDENTITY: 自增,如 mysql*                          * 底层数据库必须支持自动增长才可用(底层数据库支持的主动增长方式,对id自增)*                      GenerationType.SEQUENCE: 序列,如 oracle*                          * 底层数据库必须支持序列才可用*                      GenerationType.TABLE: JPA提供的一种机制,通过一张数据库表(hibernate_sequences)的形式帮助我们生成主键自增*                      GenerationType.AUTO: 由程序自动的帮助我们选择主键生成策略*              @Column: 配置属性和数据库表中字段的映射关系*                  name: 数据库表中字段的名称**/
@Data
@RequiredArgsConstructor()  // custName、custSource构造
@NoArgsConstructor  // 提供空参构造器!!!
@Entity
@Table(name = "cst_customer")
public class Customer {// 客户主键@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "cust_id")private long custId;// 客户名称@Column(name = "cust_name")@NonNull private String custName;// 客户来源@Column(name = "cust_source")@NonNull 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;
}

常用注解说明:

@Entity
    作用:指定当前类是实体类。
@Table
    作用:指定实体类和表之间的对应关系。
    属性:
        name:指定数据库表的名称
@Id
    作用:指定当前字段是主键。
@GeneratedValue
    作用:指定主键的生成方式。
    属性:
        strategy :指定主键生成策略。
@Column
    作用:指定实体类属性和数据库表之间的对应关系
    属性:
        name:                指定数据库表的列名称。
        unique:            是否唯一  
        nullable:            是否可以为空  
        inserttable:        是否可以插入  
        updateable:        是否可以更新  
        columnDefinition:     定义建表时创建此列的DDL  
        secondaryTable:     从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字搭建开发环境[重点]

实现保存操作测试类:src/test/java/top/onefine/test/JpaTest.java:

package top.onefine.test;import org.junit.Test;
import top.onefine.domain.Customer;import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;/*** JPA的操作步骤*  1. 加载配置文件创建工厂(实体管理类工厂)对象*  2. 通过实体管理器工厂类获取一个实体管理器*  3. 获取事务对象,开启事务*  4. 完成增删改查操作*  5. 提交事务(回滚事务)*  6. 释放资源*/
public class JpaTest {/*测试数据库的保存操作*/@Testpublic void testSave() {// 1. 加载配置文件创建工厂(实体管理类工厂)对象// 参数是持久化单元名称,值和persistence.xml中配置一致EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJPA");// 2. 通过实体管理器工厂类获取一个实体管理器EntityManager entityManager = factory.createEntityManager();// 3. 获取事务对象,开启事务// 获取事务对象EntityTransaction tx = entityManager.getTransaction();// 开启事务tx.begin();// 4. 完成增删改查操作,这里以保存为例Customer customer = new Customer("one fine", "java工程师");// 保存操作entityManager.persist(customer);// 5. 提交事务(回滚事务)tx.commit();// 6. 释放资源entityManager.close();factory.close();}
}

实现保存操作测试类:src/test/java/top/onefine/test/JpaTest.java:

package top.onefine.test;import org.junit.Test;
import top.onefine.domain.Customer;import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;/*** JPA的操作步骤*  1. 加载配置文件创建工厂(实体管理类工厂)对象*  2. 通过实体管理器工厂类获取一个实体管理器*  3. 获取事务对象,开启事务*  4. 完成增删改查操作*  5. 提交事务(回滚事务)*  6. 释放资源*/
public class JpaTest {/*测试数据库的保存操作*/@Testpublic void testSave() {// 1. 加载配置文件创建工厂(实体管理类工厂)对象// 参数是持久化单元名称,值和persistence.xml中配置一致EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJPA");// 2. 通过实体管理器工厂类获取一个实体管理器EntityManager entityManager = factory.createEntityManager();// 3. 获取事务对象,开启事务// 获取事务对象EntityTransaction tx = entityManager.getTransaction();// 开启事务tx.begin();// 4. 完成增删改查操作,这里以保存为例Customer customer = new Customer("one fine", "java工程师");// 保存操作entityManager.persist(customer);// 5. 提交事务(回滚事务)tx.commit();// 6. 释放资源entityManager.close();factory.close();}
}

四、JPA的API介绍

jpa操作的操作步骤回顾:

1.加载配置文件创建实体管理器工厂
    Persisitence:静态方法(根据持久化单元名称创建实体管理器工厂)
        createEntityMnagerFactory(持久化单元名称)
    作用:创建实体管理器工厂
    
2.根据实体管理器工厂,创建实体管理器
    EntityManagerFactory :获取EntityManager对象
    方法:createEntityManager
    * 内部维护的很多的内容
        内部维护了数据库信息,
        维护了缓存信息
        维护了所有的实体管理器对象
        在创建EntityManagerFactory的过程中会根据配置创建数据库表
    * EntityManagerFactory的创建过程比较浪费资源
    特点:线程安全的对象
        多个线程访问同一个EntityManagerFactory不会有线程安全问题
    * 如何解决EntityManagerFactory的创建过程浪费资源(耗时)的问题?
        思路:创建一个公共的EntityManagerFactory的对象
    * 静态代码块的形式创建EntityManagerFactory
    
3.创建事务对象,开启事务
    EntityManager对象:实体类管理器
        beginTransaction : 创建事务对象
        presist : 保存
        merge  : 更新
        remove : 删除
        find/getRefrence : 根据id查询
        
    Transaction 对象 : 事务
        begin:开启事务
        commit:提交事务
        rollback:回滚
4.增删改查操作
5.提交事务
6.释放资源
 

4.1 Persistence对象

Persistence对象主要作用是用于获取EntityManagerFactory对象的 。通过调用该类的createEntityManagerFactory静态方法,根据配置文件中持久化单元名称创建EntityManagerFactory。

//1. 创建 EntitymanagerFactory
@Test
String unitName = "myJPA";
EntityManagerFactory factory= Persistence.createEntityManagerFactory(unitName);
4.2 EntityManagerFactory

EntityManagerFactory 接口主要用来创建 EntityManager 实例

//创建实体管理类
EntityManager em = factory.createEntityManager();

由于EntityManagerFactory 是一个线程安全的对象(即多个线程访问同一个EntityManagerFactory 对象不会有线程安全问题),并且EntityManagerFactory 的创建极其浪费资源,所以在使用JPA编程时,我们可以对EntityManagerFactory 的创建进行优化,只需要做到一个工程只存在一个EntityManagerFactory 即可。

抽取JPAUtil工具类
src\main\java\top\onefine\utils\JpaUtils.java:

package top.onefine.utils;import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;/*** 解决实体管理器工厂创建时的资源浪费和耗时问题*      通过静态代码块的形式,当程序第一次访问此工具类时,创建一个公共的实体管理器工厂对象** 步骤:*      第一次访问getEntityManager方法:经过静态代码块创建一个factory对象,再创建一个EntityManager对象*      第二次访问getEntityManager方法:直接通过一个已经创建好的factory对象创建EntityManager对象**/
public class JpaUtils {private static EntityManagerFactory factory;static {// 加载配置文件,创建entityManagerFactoryfactory = Persistence.createEntityManagerFactory("myJPA");}// 获取EntityManager对象public static EntityManager getEntityManager() {return factory.createEntityManager();}
}
4.3 EntityManager

在 JPA 规范中, EntityManager是完成持久化操作的核心对象。实体类作为普通 java对象,只有在调用 EntityManager将其持久化后才会变成持久化对象。EntityManager对象在一组实体类与底层数据源之间进行 O/R 映射的管理。它可以用来管理和更新 Entity Bean, 根椐主键查找 Entity Bean, 还可以通过JPQL语句查询实体。

我们可以通过调用EntityManager的方法完成获取事务,以及持久化数据库的操作

方法说明:

getTransaction : 获取事务对象
persist : 保存操作
merge : 更新操作
remove : 删除操作
find/getReference : 根据id查询

4.4 EntityTransaction

在 JPA 规范中, EntityTransaction是完成事务操作的核心对象,对于EntityTransaction在我们的java代码中承接的功能比较简单

begin:开启事务
commit:提交事务
rollback:回滚事务

五、使用JPA完成增删改查操作

i.搭建环境的过程
    1.创建maven工程导入坐标
    2.需要配置jpa的核心配置文件
        *位置:配置到类路径下的一个叫做 META-INF 的文件夹下
        *命名:persistence.xml
    3.编写客户的实体类
    4.配置实体类和表,类中属性和表中字段的映射关系
    5.保存客户到数据库中

ii.完成基本CRUD案例
    persist : 保存
    merge : 更新
    remove : 删除
    find/getRefrence : 根据id查询
    
iii.jpql查询
    sql:查询的是表和表中的字段
    jpql:查询的是实体类和类中的属性
    * jpql和sql语句的语法相似
    
    1.查询全部
    2.分页查询
    3.统计查询
    4.条件查询
    5.排序

5.1 基本CRUD案例——忽略事务回滚
package top.onefine.test;import org.junit.Test;
import top.onefine.domain.Customer;
import top.onefine.utils.JpaUtils;import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;/*** JPA的操作步骤*  1. 加载配置文件创建工厂(实体管理类工厂)对象*  2. 通过实体管理器工厂类获取一个实体管理器*  3. 获取事务对象,开启事务*  4. 完成增删改查操作*  5. 提交事务(回滚事务)*  6. 释放资源*/
public class JpaTest {/*测试数据库的保存操作*/@Testpublic void testSave() {
//        // 1. 加载配置文件创建工厂(实体管理类工厂)对象
//            // 参数是持久化单元名称,值和persistence.xml中配置一致
//        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJPA");
//        // 2. 通过实体管理器工厂类获取一个实体管理器
//        EntityManager entityManager = factory.createEntityManager();EntityManager entityManager = JpaUtils.getEntityManager();// 3. 获取事务对象,开启事务// 获取事务对象EntityTransaction tx = entityManager.getTransaction();// 开启事务tx.begin();// 4. 完成增删改查操作,这里以保存为例Customer customer = new Customer("one fine", "java工程师");// 保存操作entityManager.persist(customer);// 5. 提交事务(回滚事务)tx.commit();// 6. 释放资源entityManager.close();
//        factory.close();  // 不用释放}/*** 根据id查询客户——立即加载*  使用find方法查询:*      1.查询的对象就是当前客户对象本身*      2.在调用find方法的时候,就会发送sql语句查询数据库**  立即加载*/@Testpublic void testFind() {// 1. 通过工具类获取entityManagerEntityManager entityManager = JpaUtils.getEntityManager();// 2. 开启事务EntityTransaction tx = entityManager.getTransaction();tx.begin();// 3. 增删改查——根据id查询客户/*find: 根据id查询数据class: 查询数据的结果需要包装的实体类型的字节码id: 查询的主键的取值*/Customer customer = entityManager.find(Customer.class, 1L);System.out.println(customer);// 4. 提交事务tx.commit();// 5. 释放资源entityManager.close();}/*** 根据id查询客户——懒加载*      getReference方法*          1.获取的对象是一个动态代理对象*          2.调用getReference方法不会立即发送sql语句查询数据库*              * 当调用查询结果对象的时候,才会发送查询的sql语句:什么时候用,什么时候发送sql语句查询数据库** 延迟加载(懒加载)--多使用*      * 得到的是一个动态代理对象*      * 什么时候用,什么使用才会查询*/@Testpublic void testReference() {// 1. 通过工具类获取entityManagerEntityManager entityManager = JpaUtils.getEntityManager();// 2. 开启事务EntityTransaction tx = entityManager.getTransaction();tx.begin();// 3. 增删改查——根据id查询客户/*getReference: 根据id查询数据class: 查询数据的结果需要包装的实体类型的字节码id: 查询的主键的取值*/Customer customer = entityManager.getReference(Customer.class, 1L);System.out.println(customer);// 4. 提交事务tx.commit();// 5. 释放资源entityManager.close();}/*** 删除客户*/@Testpublic void testRemove() {// 1. 通过工具类获取entityManagerEntityManager entityManager = JpaUtils.getEntityManager();// 2. 开启事务EntityTransaction tx = entityManager.getTransaction();tx.begin();// 3. 增删改查——删除客户// 根据id查询客户Customer customer = entityManager.find(Customer.class, 3L);// 调用remove方法完成删除操作if (customer != null) {System.out.println(customer + "已删除");entityManager.remove(customer);}// 4. 提交事务tx.commit();// 5. 释放资源entityManager.clear();}/*** 更新客户*/@Testpublic void testUpdate() {// 1. 通过工具类获取entityManagerEntityManager entityManager = JpaUtils.getEntityManager();// 2. 开启事务EntityTransaction tx = entityManager.getTransaction();tx.begin();// 3. 增删改查——更新客户// 查询客户Customer customer = entityManager.find(Customer.class, 1L);// 更新客户if (customer != null) {System.out.println("更新前: " + customer);customer.setCustLevel("6段...");Customer update_customer = entityManager.merge(customer);//            System.out.println("更新后: " + entityManager.find(Customer.class, 1L));System.out.println("更新后: " + update_customer);}// 4. 提交事务tx.commit();// 5. 释放资源entityManager.clear();}
}
5.2 JPQL查询

JPQL全称Java Persistence Query Language,基于首次在EJB2.0中引入的EJB查询语言(EJB QL),Java持久化查询语言(JPQL)是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL。

其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性。

package top.onefine.test;import org.junit.Test;
import top.onefine.domain.Customer;
import top.onefine.utils.JpaUtils;import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import java.util.List;/*** 测试jpql查询*      步骤:*          1. 创建query查询对象*          2. 对参数进行赋值*          3. 查询,并得到返回结果*/
public class JpqlTest {/*** 查询全部*      jqpl:from [top.onefine.]Customer*      sql:select * from cst_customer*/@Testpublic void testFindAll() {// 1. 通过工具类获取entityManagerEntityManager entityManager = JpaUtils.getEntityManager();// 2. 开启事务EntityTransaction tx = entityManager.getTransaction();tx.begin();// 3. 查询全部// 创建Query查询对象,query对象才是执行jqpl的对象String jpql = "from " + /*"top.onefine.domain." + */"Customer";Query query = entityManager.createQuery(jpql);// 发送查询,并封装结果集List<Customer> list = query.getResultList();for (Customer customer : list)System.out.println(customer);// 4. 提交事务tx.commit();// 5. 释放资源entityManager.clear();}/*** 排序查询:根据id倒序查询全部客户*      jqpl:from [top.onefine.]Customer order by custId desc*      sql:select * from cst_customer order by cust_id desc*/@Testpublic void testOrders() {// 1. 通过工具类获取entityManagerEntityManager entityManager = JpaUtils.getEntityManager();// 2. 开启事务EntityTransaction tx = entityManager.getTransaction();tx.begin();// 3. 排序查询// 创建Query查询对象,query对象才是执行jqpl的对象String jpql = "from " + /*"top.onefine.domain." + */"Customer order by custId desc";  // custId是实体类属性名称Query query = entityManager.createQuery(jpql);// 发送查询,并封装结果集List<Customer> list = query.getResultList();for (Customer customer : list)System.out.println(customer);// 4. 提交事务tx.commit();// 5. 释放资源entityManager.clear();}/*** 统计查询:统计客户的总数*      jqpl:select count(custId) from [top.onefine.]Customer*      sql:select count(cust_id) from cst_customer*/@Testpublic void testCount() {// 1. 通过工具类获取entityManagerEntityManager entityManager = JpaUtils.getEntityManager();// 2. 开启事务EntityTransaction tx = entityManager.getTransaction();tx.begin();// 3. 统计查询// 根据jpql语句创建query查询条件String jpql = "select count(custId) from " + /*"top.onefine.domain." + */"Customer";  // custId是实体类属性名称// 对参数赋值// 发送查询,并封装结果Query query = entityManager.createQuery(jpql);
//        // 发送查询,并封装结果集
//        List list = query.getResultList();
//
//        for (Object customer : list)
//            System.out.println(customer);// 注:getResultList是直接将查询结果封装为list集合// getSingleResult得到唯一的结果Object result = query.getSingleResult();System.out.println((long) result);// 4. 提交事务tx.commit();// 5. 释放资源entityManager.clear();}/*** 分页查询*      jqpl:from [top.onefine.]Customer*      sql:select * from cst_customer limit ?, ? // 占位符,如 limit 0, 2*/@Testpublic void testPaged() {// 1. 通过工具类获取entityManagerEntityManager entityManager = JpaUtils.getEntityManager();// 2. 开启事务EntityTransaction tx = entityManager.getTransaction();tx.begin();// 3. 分页查询// 根据jpql语句创建query查询条件String jpql = "from " + /*"top.onefine.domain." + */"Customer";Query query = entityManager.createQuery(jpql);// 对参数赋值——分页参数// 起始索引query.setFirstResult(0);// 每页查询的条数query.setMaxResults(2);// 发送查询,并封装结果List list = query.getResultList();for (Object customer : list)System.out.println(customer);// 4. 提交事务tx.commit();// 5. 释放资源entityManager.clear();}/*** 条件查询:查询客户名称以"one"开头的客户*      jqpl:from [top.onefine.]Customer where custName like ?*      sql:select * from cst_customer where cust_name like ?*/@Testpublic void testCondition() {// 1. 通过工具类获取entityManagerEntityManager entityManager = JpaUtils.getEntityManager();// 2. 开启事务EntityTransaction tx = entityManager.getTransaction();tx.begin();// 3. 条件查询// 根据jpql语句创建query查询条件String jpql = "from " + /*"top.onefine.domain." + */"Customer where custName like ?1";Query query = entityManager.createQuery(jpql);// 对参数赋值——占位符参数// 第一个参数是占位符的索引位置(从1开始),第二个参数是取值query.setParameter(1, "one%");// 发送查询,并封装结果List list = query.getResultList();for (Object customer : list)System.out.println(customer);// 4. 提交事务tx.commit();// 5. 释放资源entityManager.clear();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/51556.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLO v8目标检测(三)模型训练与正负样本匹配

YOLO v8目标检测 损失函数理论 在YOLO v5模型中&#xff0c;cls, reg, obj代表的是三个不同的预测组成部分&#xff0c;对应的损失函数如下&#xff1a; cls: 这代表类别预测&#xff08;classification&#xff09;。对应的损失是类别预测损失&#xff08;loss_cls&#xff…

简单快速收集_安居客二手房小区数据

安居客二手房小区全国实时数据&#xff0c;含小区名称、价格、地区、地址、商圈、标签、经纬度、物业类型、交易权属、竣工时间、产权年限、开发商、总户数、总建面积、绿化率、容积率、统一供暖 供水供电、停车位、停车费、物业费、物业公司 车位管理费、在售房源、在租房源 …

B端:导航条就框架提供的默认样式吗?非也,看过来。

导航条不一定必须使用框架提供的默认样式&#xff0c;你可以根据项目需求和设计风格进行自定义。通过使用框架提供的自定义选项、CSS样式覆盖、自行设计或者使用其他UI库或组件&#xff0c;你可以实现独特且符合需求的导航条样式。 下面发一些参考给友友们&#xff0c;可以让设…

论文解读:DiAD之SG网络

目录 一、SG网络功能介绍二、SG网络代码实现 一、SG网络功能介绍 DiAD论文最主要的创新点就是使用SG网络解决多类别异常检测中的语义信息丢失问题&#xff0c;那么它是怎么实现的保留原始图像语义信息的同时重建异常区域&#xff1f; 与稳定扩散去噪网络的连接&#xff1a; S…

昇思25天学习打卡营第3天|基础知识-数据集Dataset

目录 环境 环境 导包 数据集加载 数据集迭代 数据集常用操作 shuffle map batch 自定义数据集 可随机访问数据集 可迭代数据集 生成器 MindSpore提供基于Pipeline的数据引擎&#xff0c;通过数据集&#xff08;Dataset&#xff09;和数据变换&#xff08;Transfor…

skynet 入门篇

文章目录 概述1.实现了actor模型2.实现了服务器的基础组件 环境准备centosubuntumac编译安装 ActorActor模型定义组成 Actor调度工作线程流程工作线程权重工作线程执行规则 小结 概述 skynet 是一个轻量级服务器框架&#xff0c;而不仅仅用于游戏&#xff1b; 轻量级有以下几…

C语言百分号打印器

目录 开头程序程序的流程图程序输入与输出的效果例1输入输出 例2输入输出 例3输入输出 结尾 开头 大家好&#xff0c;我叫这是我58。今天&#xff0c;我们来看一下我用C语言编译的百分号打印器和与之相关的一些东西。 程序 #define _CRT_SECURE_NO_WARNINGS 1 #include <…

【RabbitMQ】MQ相关概念

一、MQ的基本概念 定义&#xff1a;MQ全称为Message Queue&#xff0c;是一种提供消息队列服务的中间件&#xff0c;也称为消息中间件。它允许应用程序通过读写队列中的消息来进行通信&#xff0c;而无需建立直接的连接。作用&#xff1a;主要用于分布式系统之间的通信&#x…

CANoe在使用时碰到的一些很少见的Bug

CANoe作为一款成熟且稳定的总线仿真与测试工具&#xff0c;深受汽车工程师们的喜爱。CANoe虽然稳定&#xff0c;但作为一个软件来说&#xff0c;在使用中总会出现一些或大或小的Bug。最近全球范围内的大规模蓝屏事件&#xff0c;是由某个安全软件引起的。而很多CANoe使用者最近…

【中项】系统集成项目管理工程师-第7章 软硬件系统集成-7.2基础设施集成

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…

【React】详解classnames工具:优化类名控制的全面指南

文章目录 一、classnames的基本用法1. 什么是classnames&#xff1f;2. 安装classnames3. 导入classnames4. classnames的基本示例 二、classnames的高级用法1. 动态类名2. 传递数组3. 结合字符串和对象4. 结合数组和对象 三、实际应用案例1. 根据状态切换类名2. 条件渲染和类名…

Kafka消息队列

目录 什么是消息队列 高可用性 高扩展性 高可用性 持久化和过期策略 consumer group 分组消费 ZooKeeper 什么是消息队列 普通版消息队列 说白了就是一个队列,生产者生产多少,放在消息队列中存储,而消费者想要多少拿多少,按序列号消费 缓存信息 生产者与消费者解耦…

VulnHub靶机入门篇--Kioptrix4

1.环境配置 下载地址&#xff1a; https://download.vulnhub.com/kioptrix/Kioptrix4_vmware.rar 下载完解压之后是一个vdmk文件&#xff0c;我们需要先创建一个新的虚拟机&#xff0c;将vdmk文件导入就行了 先移除原先硬盘&#xff0c;然后再进行添加&#xff0c;网络连接为…

EV代码签名证书具体申请流程

EV&#xff08;扩展验证&#xff09;代码签名证书是一种用于对代码进行数字签名的安全证书&#xff0c;它可以帮助用户验证软件发布者的身份&#xff0c;并确保软件未被篡改。对于Windows硬件开发者来说&#xff0c;这种证书尤其重要&#xff0c;因为它可以用来注册Windows硬件…

【Golang 面试 - 基础题】每日 5 题(八)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

六、2 写PWM代码(函数介绍、呼吸灯代码)

目录 一、1、步骤 2、函数介绍 3、外设引脚和GPIO引脚的复用关系&#xff08;引脚定义表&#xff09; 二、1、呼吸灯 步骤 &#xff08;1&#xff09;初始化通道 1&#xff09;输出比较模式 2&#xff09;输出比较极性 &#xff08;2&#xff09;配置GPIO &#xff08…

肆[4],VisionMaster全局触发测试说明

1&#xff0c;环境 VisionMaster4.3 2&#xff0c;实现功能 2.1&#xff0c;全局触发进行流程控制执行。 2.2&#xff0c;取像完成&#xff0c;立即运动到下一个位置&#xff0c;同步进行图片处理。 2.3&#xff0c;发送结果的同时&#xff0c;还需要显示图像处理的痕迹。 …

H616设计时候存在的问题

1.存在大量孤铜的问题&#xff1a; 这种情况是绝对不允许的&#xff0c;但是GBA焊盘打大量的过孔会出现很多这样的孤铜&#xff1a; 解决办法&#xff1a; 像这种出现大量重复焊盘的&#xff0c;用导线连接起来&#xff0c;之后铺铜形成铜皮&#xff0c;再在这个小铜皮上面打…

全网首创!基于GaitSet的一种多人步态识别方法公示

有源代码V细聊&#xff0c;可商用/私用/毕设等&#xff1a;NzqDssm16 &#x1f349;1 绪论 经过相关研究确认&#xff0c;步态识别是足以达到应用级别的生物识别技术&#xff0c;在现代社会中自始至终都存在着广泛的应用前景。之所以迟迟没有普及&#xff0c;主要是实…

【Oracle 进阶之路】Oracle 简介

一、简述 Oracle Database&#xff0c;又名Oracle RDBMS&#xff0c;或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是世界上流行的关系数据库管理系统&#xff0c;系统可移植性好、使用方便、功能强&…