JPA基本使用,java工作三年面试题

本文详细介绍了JPA的核心组件,包括Persistence、EntityManagerFactory和EntityManager的使用,以及事务管理、主键生成策略。通过示例展示了如何进行增删改查操作,并探讨了JPA的复杂查询,如JPQL的使用、分页、条件和排序查询。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JPA的API介绍


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

String unitName = “myJpa”;

EntityManagerFactory factory= Persistence.createEntityManagerFactory(unitName);

EntityManagerFactory:主要用来创建 EntityManager 实例,由于EntityManagerFactory 是一个线程安全的对象(即多个线程访问同一个EntityManagerFactory 对象不会有线程安全问题),并且EntityManagerFactory 的创建极其浪费资源,所以在使用JPA编程时,我们可以对其进行优化,满足一个项目中只有一个EntityManagerFactory。

//创建实体管理类

EntityManager em = factory.createEntityManager();

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

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

  • getTransaction : 获取事务对象

  • persist : 保存操作

  • merge : 更新操作

  • remove : 删除操作

  • find/getReference : 根据id查询

EntityTransaction: 在 JPA 规范中,EntityTransaction是完成事务操作的核心对象,对于EntityTransaction在我们的java代码中承接的功能比较简单begin:开启事务commit:提交事务rollback:回滚事务

测试代码:

@Test

public void test() {

/**

  • 创建实体管理类工厂,借助Persistence的静态方法获取

  •   其中传递的参数为持久化单元名称,需要jpa配置文件中指定
    

*/

EntityManagerFactory factory = Persistence.createEntityManagerFactory(“myJpa”);

//创建实体管理类,工厂对象

EntityManager em = factory.createEntityManager();

//获取事务对象,通过实体管理类工厂获取实体管理器

EntityTransaction tx = em.getTransaction();

//开启事务,获取事务对象

tx.begin();

//完成增删改查操作

Customer c = new Customer();

c.setCustName(“客户1”);

c.setCustIndustry(“程序员”);

//保存操作

em.persist©;

//提交事务(回滚事务)

tx.commit();

//释放资源

em.close();

factory.close();

}

JPA中的主键生成策略:

  • IDENTITY: 主键由数据库自动生成(主要是自动增长型)

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long custId;

  • SEQUENCE: 根据底层数据库的序列来生成主键,条件是数据库支持序列。

@Id

@GeneratedValue(strategy = GenerationType.SEQUENCE,generator=“payablemoney_seq”)

@SequenceGenerator(name=“payablemoney_seq”, sequenceName=“seq_payment”)

private Long custId;

  • AUTO: 主键由程序控制

@Id

@GeneratedValue(strategy = GenerationType.AUTO)

private Long custId;

  • TABLE: 使用一个特定的数据库表格来保存主键

@Id

@GeneratedValue(strategy = GenerationType.TABLE, generator=“payablemoney_gen”)

@TableGenerator(name = “pk_gen”,

table=“tb_generator”,

pkColumnName=“gen_name”,

valueColumnName=“gen_value”,

pkColumnValue=“PAYABLEMOENY_PK”,

allocationSize=1

) private Long custId;

使用JPA完成增删改查操作


1. 抽取JPAUtil工具类:

通过静态代码块的形式, 解决实体管理类(EntityManagerFactory)工厂资源浪费和耗时问题。 使用静态代码块,当程序第一次访问此工具类的getEntityManager方法,经过静态代码块创建一个factory对象,再次调用方法创建一个EntityManager对象,当程序第二次访问getEntityManager方法时,直接通过一个已经创建好的factory对象,创建EntityManager对象。

/**

  • @Author: Ly

  • @Date: 2020-11-27 21:09

*/

public class JpaUtils {

// JPA的实体管理器工厂:相当于Hibernate的SessionFactory

private static EntityManagerFactory factory;

// 使用静态代码块赋值

static {

// 注意:该方法参数必须和persistence.xml中persistence-unit标签name属性取值一致

factory = Persistence.createEntityManagerFactory(“myJpa”);

}

/**

  • 使用管理器工厂生产一个管理器对象

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

@return

*/

public static EntityManager getEntityManager() {

return factory.createEntityManager();

}

}

2. 测试增删改查:

  • persist :保存

  • merge : 更新

  • remove : 删除

  • find/getRefrence:根据id查询

class::查询数据的结果需要包装的实体类类型的字节码

id: 查询主键的取值

2.1 保存

@Test

public void testSave() {

EntityManager em = JpaUtils.getEntityManager();

//获取事务对象,通过实体管理类工厂获取实体管理器

EntityTransaction tx = em.getTransaction();

//开启事务,获取事务对象

tx.begin();

//完成保存操作

Customer customer = new Customer();

customer.setCustName(“客户2”);

customer.setCustIndustry(“教育”);

//保存操作

em.persist(customer);

//提交事务(回滚事务)

tx.commit();

//释放资源

em.close();

}

2.2 修改

@Test

public void testUpdate() {

EntityManager em = JpaUtils.getEntityManager();

//获取事务对象,通过实体管理类工厂获取实体管理器

EntityTransaction tx = em.getTransaction();

//开启事务,获取事务对象

tx.begin();

//更新客户

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

customer.setCustIndustry(“IT教育”);

em.merge(customer);

//提交事务(回滚事务)

tx.commit();

//释放资源

em.close();

}

2.3 删除

@Test

public void testRemove() {

EntityManager em = JpaUtils.getEntityManager();

//获取事务对象,通过实体管理类工厂获取实体管理器

EntityTransaction tx = em.getTransaction();

//开启事务,获取事务对象

tx.begin();

//删除客户

//根据id查询

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

//删除用户

em.remove(customer);

//提交事务(回滚事务)

tx.commit();

//释放资源

em.close();

}

2.4 根据id查询

find与getReference:

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

  • getReference: 查询对象是一个动态代理对象,调用getReference方法立即发送sql语句查询数据,当调用查询结果对象的时候,才会发送查询的sql语句,即什么时候用,什么时候发送sql语句查询数据库 (延迟加载)

@Test

public void testFind() {

//通过工具类获取 entityManager

EntityManager em = JpaUtils.getEntityManager();

//获取事务对象,通过实体管理类工厂获取实体管理器

EntityTransaction tx = em.getTransaction();

//开启事务,获取事务对象

tx.begin();

//完成查询操作

//Customer customer = em.find(Customer.class,1l);

Customer customer = em.getReference(Customer.class,1l);

System.out.println(customer);

//提交事务(回滚事务)

tx.commit();

//释放资源

em.close();

}

JPA中的复杂查询


JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB查询语言的一种扩展,以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起。它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,因此其具有可移植性,可以被编译成所有主流数据库服务器上的SQL。其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性。

JPQL支持批量更新和修改、JOIN、GROUP BY、HAVING 等高级查询特性,同时还能够支持子查询

1. 查询全部

//查询所有客户

@Test

public void findAll() {

EntityManager em = null;

EntityTransaction tx = null;

try {

//获取实体管理对象

em = JpaUtils.getEntityManager();

//获取事务对象

tx = em.getTransaction();

tx.begin();

// 创建query对象

//jqpl: from com.ly.domain.Customer

//sql: select * from cst_cus_customer

String jpql = “from Customer”;

Query query = em.createQuery(jpql);

// 查询并得到返回结果

List list = query.getResultList(); // 得到集合返回类型

for (Object object : list) {

System.out.println(object);

}

tx.commit();

} catch (Exception e) {

// 回滚事务

tx.rollback();

e.printStackTrace();

} finally {

// 释放资源

em.close();

}

}

2. 分页查询

//分页查询客户

@Test

public void findPaged () {

EntityManager em = null;

EntityTransaction tx = null;

try {

//获取实体管理对象

em = JpaUtils.getEntityManager();

//获取事务对象

tx = em.getTransaction();

tx.begin();

//创建query对象

String jpql = “from Customer”;

Query query = em.createQuery(jpql);

//起始索引

query.setFirstResult(0);

//每页显示条数

query.setMaxResults(2);

//查询并得到返回结果

List list = query.getResultList(); //得到集合返回类型

for (Object object : list) {

System.out.println(object);

}

tx.commit();

} catch (Exception e) {

// 回滚事务

tx.rollback();

e.printStackTrace();

} finally {

// 释放资源

em.close();

}

}

3. 条件查询

//条件查询

@Test

public void findCondition () {

EntityManager em = null;

EntityTransaction tx = null;

try {

//获取实体管理对象

em = JpaUtils.getEntityManager();

//获取事务对象

tx = em.getTransaction();

tx.begin();

//创建query对象

String jpql = "from Customer where custName like ? ";

Query query = em.createQuery(jpql);

//对占位符赋值,从1开始

query.setParameter(1, “传智播客%”);

//查询并得到返回结果

Object object = query.getSingleResult(); //得到唯一的结果集对象

System.out.println(object);

tx.commit();

} catch (Exception e) {

// 回滚事务

tx.rollback();

e.printStackTrace();

} finally {

// 释放资源

em.close();

}

}

4. 排序查询

//根据客户id倒序查询所有客户

//查询所有客户

@Test

public void testOrder() {

EntityManager em = null;

EntityTransaction tx = null;

try {

//获取实体管理对象

em = JpaUtils.getEntityManager();

//获取事务对象

tx = em.getTransaction();

tx.begin();

// 创建query对象

String jpql = “from Customer order by custId desc”;

Query query = em.createQuery(jpql);

// 查询并得到返回结果

List list = query.getResultList(); // 得到集合返回类型

for (Object object : list) {

System.out.println(object);

}

tx.commit();

} catch (Exception e) {

// 回滚事务

tx.rollback();

e.printStackTrace();

} finally {

// 释放资源

em.close();

}

}

5. 统计查询

//统计查询

@Test

public void findCount() {

EntityManager em = null;

EntityTransaction tx = null;

try {

//获取实体管理对象

em = JpaUtils.getEntityManager();

//获取事务对象

tx = em.getTransaction();

tx.begin();

// 查询全部客户

// 1.创建query对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值