
JPA与Hibernate
文章平均质量分 55
Java技术集锦
孙卫琴,知名IT作家和Java开发专家,毕业于上海交通大学,已经创作了近二十部软件开发领域的专著,多部作品在同类书籍中位居全国畅销排行榜的榜首。代表著作有:《漫画Java编程》、《精通Spring:Java Web开发技术详解》、《精通Vue.js:Web前端开发技术详解》、《Java面向对象编程》、《Java网络编程核心技术详解》、《精通JPA与Hibernate: Java对象持久化技术详解》、《Tomcat与Java Web开发技术详解》。
展开
-
孙卫琴的《精通JPA与Hibernate》的读书笔记:JPA的事件处理API的用法
JPA API也提供了处理事件的办法,它主要包括两个步骤:(1)创建监听器类。(2)在持久化类中通过@EntityListeners注解来注册监听器。1.创建监听器类监听器类不需要实现特定的接口,可以是任意的Java类,例如以下MyLastUpdateListener类就是一个监听器类。/* MyLastUpdateListener.java */package mypack;import javax.persistence.*;import java.util.*;public clas原创 2022-08-31 09:04:19 · 214 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记: 用JPQL批量处理数据
JPA的JPQL(JPA Query Language,JPA查询语言)不仅可以检索数据,还可以用于进行批量更新、删除和插入数据。批量操作实际上直接在数据库中完成,所处理的数据不会被保存在Session的持久化缓存中,因此不会占用内存空间。Query.executeUpdate()方法和JDBC API中的PreparedStatement.executeUpdate()很相似,前者执行用于更新、删除和插入的JPQL语句,而后者执行用于更新、删除和插入的SQL语句。1.批量更新数据以下程序代码演示通过原创 2022-08-31 09:03:57 · 290 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:通过JPA处理Blob和Clob类型的数据
在持久化类中,二进制大对象可以声明为byte[]或java.sql.Blob类型;字符串大对象可以声明为java.lang.String或java.sql.Clob类型。java.sql.Blob和java.sql.Clob是JDBC API中的接口。在默认情况下,Blob和Clob接口的实现会使用SQL定位器,这意味着当程序从数据库加载Blob类型或Clob类型的数据时,实际上加载的仅是Blob类型或Clob类型的数据的逻辑指针。接下来程序需要通过Blob.getBinaryStream()或Clob.原创 2022-08-31 09:03:30 · 1036 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:每个具体类对应一张表的继承映射
表的结构如下:在域模型中,Company类和Employee类之间为一对多的双向关联关系(假定不允许雇员同时在多个公司兼职),Employee类为抽象类,因此它不能被实例化,它有两个具体的子类:HourlyEmployee类和SalariedEmployee类。由于Java只允许一个类最多有一个直接的父类,因此Employee类、HourlyEmployee类和SalariedEmployee类构成了一棵继承关系树。1.映射Company类Company类与Employee类是一对多的关联关系,C原创 2021-05-07 10:23:36 · 233 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:映射继承关系之一(根类对应一张表)
表的结构如下:在域模型中,Company类和Employee类之间为一对多的双向关联关系(假定不允许雇员同时在多个公司兼职),Employee类为抽象类,因此它不能被实例化,它有两个具体的子类:HourlyEmployee类和SalariedEmployee类。由于Java只允许一个类最多有一个直接的父类,因此Employee类、HourlyEmployee类和SalariedEmployee类构成了一棵继承关系树。1.映射Company类Company类与Employee类是一对多的关联关系,C原创 2021-05-07 10:22:38 · 306 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:映射Set集(值类型的集合)
假定Customer对象的images集合中不允许存放重复的照片文件名,因此可以把images属性定义为Set类型:private Set<String> images=new HashSet<String>();在数据库中定义了一张IMAGES表,它的CUSTOMER_ID字段为参照CUSTOMERS表的外键,由于Customer对象不允许有重复的照片文件名,因此应该把IMAGES表的CUSTOMER_ID和FILENAME字段作为联合主键。以下是IMAGES表的DDL定原创 2021-05-06 22:47:08 · 198 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:Spring与Hibernate与JPA的整合(详细配置和源码)
1. 设置Spring的配置文件在Spring的配置文件applicationContext.xml中,配置C3P0数据源、EntityManagerFactory、JpaTransactionManager等Bean组件。applicationContext.xml文件位于范例程序的classpath根路径下,以下是它的源程序。/* applicationContext.xml */<?xml version="1.0" encoding="UTF-8"?><beans xml原创 2021-05-06 22:46:48 · 450 阅读 · 1 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:映射Bag包(值类型的集合)
Bag集合中的对象不按特定方式排序,但是允许有重复对象。在Java集合API中并没有提供Bag接口,Hibernate允许在持久化类中用List来模拟Bag的行为。假定Customer对象的images集合中允许存放重复的照片文件名,可以把images属性定义为List类型:private List<String> images=new ArrayList<String>();在数据库中定义了一张IMAGES表,它的CUSTOMER_ID字段为参照CUSTOMERS表的外键,由原创 2021-05-06 22:46:32 · 216 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:用@ManyToMany注解映射双向关联
假定建立了从Category(商品类别)类和Item(商品)类的双向多对多关联。在Category类中需要定义集合类型的items属性,并且在Item类也需要定义集合类型的categories属性。下图显示了Category类和Item类的关联关系。下图显示了CATEGORIES表、ITEMS表和CATEGORY_ITEM表的结构。在Category类中,映射items属性的代码如下所示:@ManyToMany(cascade=CascadeType.PERSIST)@JoinTable( .原创 2021-05-06 22:45:53 · 225 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:FetchType.LAZY延迟检索策略
对于一对多关联和多对多关联,应该优先考虑使用默认的延迟检索策略。在Customer类中,以下代码对orders集合属性采用延迟检索策略://采用默认的延迟检索策略@OneToMany(mappedBy="customer")private Set<Order> orders = new HashSet<Order>();或者://显式设置延迟检索策略@OneToMany(mappedBy="customer", fetch=FetchType.原创 2021-05-06 22:45:08 · 248 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:用@OneToOne注解映射一对一关联
在以下图中,ADDRESSES表的ID字段既是主键,同时作为外键参照CUSTOMERS表的主键,也就是说,ADDRESSES表与CUSTOMERS表共享主键。 在Customer类中,也是用@OneToOne注解来映射homeAddress属性: @OneToOne( cascade=CascadeType.ALL, mappedBy="customer" ) private Address homeAddress;在Customer类与Address类的双向一对一关联关原创 2021-05-06 22:44:40 · 306 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记: 通过JPA API中的StoredProcedureQuery接口调用存储过程
以下SQL代码定义了一个名为findCustomers的存储过程,p_age为输入参数,p_count为输出参数:delimiter //create procedure findCustomers(in p_age integer,out p_count integer)beginselect count(*) into p_count from CUSTOMERS where AGE>p_age;select name from CUSTOMERS;end //JPA API中原创 2021-05-06 22:44:17 · 1020 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:在程序中动态指定立即左外连接检索
在持久化类中通过注解设定的检索策略是固定的,要么为延迟检索,要么为立即检索。但应用逻辑是多种多样的,有些情况下需要延迟检索,而有些情况下需要立即检索。Hibernate允许在应用程序中覆盖持久化类中设定的检索策略,由应用程序在运行时决定检索对象图的深度。以下代码两次调用Query的getResultList()方法,都用于检索OID为1的Customer对象://第一个Query.getResultList()方法entityManager .createQuery("from Cust原创 2021-05-06 22:43:14 · 205 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:区分持久化类的值类型和实体类型的属性
如果Address类没有OID,那它就是组件类。由于Address类没有OID,因此不能通过EntityManager或Session来单独保存、更新、删除或加载一个Address对象。例如,以下每行代码都会抛出IllegalArgumentException异常:entityManager.find(Address.class,Long.valueOf(1)); entityManager.persist(address);entityManager.remove(address); 以上代码运原创 2021-05-06 22:42:45 · 280 阅读 · 1 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记: 映射组成关系
建立域模型和关系数据模型有着不同的出发点:域模型是由程序代码组成的,通过细化持久化类的粒度可提高代码可重用性,简化编程。关系数据模型是由关系数据组成的。在存在数据冗余的情况下,需要把粗粒度的表拆分成具有外键参照关系的几个细粒度的表,从而节省存储空间;另一方面,在没有数据冗余的前提下,应该尽可能减少表的数目,简化表之间的参照关系,以便提高访问数据库的速度。因此,在建立关系数据模型时,需要在节省数据存储空间和节省数据操纵时间这两者之间进行折中。由于建立域模型和关系数据模型的原则不一样,使得持久化类的数原创 2021-05-06 22:42:15 · 216 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:JPQL检索方式的基本用法
JPQL(JPA Query Language)是面向对象的查询语言,它和SQL查询语言有些相似。在JPA提供的各种检索方式中,JPQL是使用最广的一种检索方式。它具有以下功能:在查询语句中设定各种查询条件。支持投影查询,即仅检索出对象的部分属性。支持分页查询。支持连接查询。支持分组查询,允许使用having和group by关键字。支持调用各种函数。支持子查询,即嵌入式查询。支持动态绑定参数。以下程序代码用于检索姓名为“Tom”,并且年龄为21的Customer对象://创建一个Q原创 2021-05-05 10:22:46 · 249 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:JPA QBC检索的基本用法
采用JPQL检索方式时,在应用程序中需要定义基于字符串形式的JPQL查询语句。QBC API提供了检索对象的另一种方式,它提供了一种更加面向对象的查询方法,应用程序不需要提供查询语句,而是通过QBC API中的相关的接口和类来设定需要检索的数据,包括设定检索条件等。QBC API位于javax.persistence.criteria包中,主要包括以下接口:CriteriaBuilder接口:它是生成CriteriaQuery实例的工厂类。CriteriaQuery接口:它是主要的查询接口,通过它来原创 2021-05-05 10:22:00 · 278 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:JPA 分页查询
当批量查询数据时(例如查询CUSTOMERS表中所有记录),如果数据量很大,会导致无法在用户终端的单个页面上显示所有的查询结果,此时需要对查询结果分页。假如CUSTOMER表中有99条记录,可以在用户终端上分10页来显示结果,每一页最多只显示10个Customer对象,用户既可以导航到下一页,也可以导航到前一页。Query接口提供了用于分页获取查询结果的方法:setFirstResult(int firstResult):设定从哪一个对象开始检索,参数firstResult表示这个对象在查询结果中的索原创 2021-05-05 10:20:31 · 305 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记: JPQL和QBC查询的绑定参数
1. JPQL的参数绑定1.1 按参数名字绑定在JPQL查询语句中定义命名参数,命名参数以“:”开头,形式如下:TypedQuery<Customer> query=entityManager.createQuery( "from Customer as c where c.name=:customerName " +"and c.age=:customerAge",Customer.class);以上JPQL查询语句定义了两个命名参数“customerName原创 2021-05-05 10:19:24 · 317 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:JPQL与QBC的分组查询
JPQL查询语句中的group by 子句用于分组查询,它和SQL中的用法很相似。下面举例说明它的用法。(1)按照姓名分组,统计CUSTOMERS表中具有相同姓名的记录的数目://JPQL检索方式Iterator<Object[]> it=entityManager .createQuery("select c.name,count(c) from Customer c group by c.name", Object[].class) .get原创 2021-05-05 10:18:17 · 264 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记: JPQL和QBC的各种连接查询
1. 立即左外连接以下程序覆盖映射代码中指定的检索策略,显式指定对与Customer关联的Order对象采用立即左外连接检索策略://JPQL检索方式List<Customer> result=entityManager .createQuery("from Customer c left join fetch c.orders o " +"where c.name like 'T%' ",Customer.class) .getResultList();//QBC检索方式原创 2021-05-05 10:17:33 · 413 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:配置数据源,由容器提供
在受管理环境中,如JBoss应用服务器,由容器负责构造数据源,即javax.sql.DataSource的实例,然后把它发布为JNDI资源,Hibernate的DataSourceConnectionProviderImpl类充当这个数据源的代理,这个类位于org.hibernate.engine.jdbc.connections.internal包中。有些Servlet容器,如Tomcat,也能负责构造数据源,并能把它发布为JNDI资源,因此Hibernate也能从Tomcat容器中获得数据源。以To原创 2021-05-05 10:15:48 · 227 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:声明JTA事务
Java应用通过JTA API声明JTA事务的步骤如下。(1)在Hibernate配置文件中配置数据源以及JTA平台属性:hibernate.connection.datasource= java:comp/env/jdbc/SAMPLEDB hibernate.transaction.coordinator_class=jtahibernate.transaction.jta.platform=JBossTS(2)在程序中创建javax.naming.InitialContext对象:Con原创 2021-05-05 10:14:45 · 282 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记: 用乐观锁避免并发问题
乐观锁是由应用程序提供的一种机制,这种机制既能保证多个事务并发访问数据,又能防止第二类丢失更新问题。在应用程序中,可以利用Hibernate提供的版本控制功能来实现乐观锁。既可以用一个递增的整数来表示版本号,也可以用时间戳来表示版本号,跟踪数据库表中记录的版本。下面介绍利用整数类型的版本控制属性对ACCOUNTS表中记录进行版本控制的步骤。(1)在Account类中定义一个代表版本信息的version属性,这个属性用@Version注解来标识:@Version@Column(name="VERSIO原创 2021-05-05 10:12:53 · 261 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:在程序中控制第二级缓存Cache
EntityManager的detach()方法用于从第一级缓存中清除一个特定的对象。对于第二级缓存,JPA API提供了javax.persistence.Cache接口,它具有控制第二级缓存的evict()方法,能从第二级缓存的实体数据缓存中删除特定的数据。javax.persistence.Cache接口只能控制实体数据缓存。如果要控制其他类型的缓存,需要使用Hibernate API提供的org.hibernate.Cache接口。以下controlCache()方法演示了JPA API以及Hi原创 2021-05-05 10:09:04 · 292 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:EntityManager和Session的merge()方法详解
JPA API 的EntityManager 以及Hibernate API的Session都有一个merge()方法,它们的作用相同,能够把一个游离对象的属性复制到一个持久化对象中。当Session用update()方法关联一个游离对象时,如果在持久化缓存中已经存在一个同类型的并且OID相同的持久化对象,那么update()方法会抛出NonUniqueObjectException:customer1.setName("Jack");//假定customer1为游离对象,OID为1Session原创 2021-05-04 15:33:28 · 369 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:JPA API的级联操作
在JPA API中,javax.persistence.CascadeType类中定义了一些常量,分别表示特定的级联操作:CascadeType.PERSIST :当通过EntityManager的persist()方法来保存当前对象时,会级联保存所有关联的新建的临时对象。CascadeType.REMOVE :当通过EntityManager的remove()方法来删除当前持久化对象时,会级联删除所有关联的持久化对象。CascadeType.DETACH :当通过EntityManager的det原创 2021-05-04 15:28:41 · 337 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:用orphanRemoval属性映射父子关系
以下是removeOrderFromCustomer()方法的代码,它先加载一个Customer对象,然后获得与Customer对象关联的一个Order对象的引用,最后解除Customer和Order对象之间的关系:tx = entityManager.getTransaction(); tx.begin(); //开始一个事务//加载Customer对象Customer customer=entityManager.find(Customer.class,customerId);//获得与C原创 2021-05-04 13:18:09 · 435 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:映射一对多双向关联关系
当类与类之间建立了关联,就可以方便地从一个对象导航到另一个或者一组与它关联的对象。例如,对于给定的Order对象,如果想获得与它关联的Customer对象,只要调用如下方法://从Order对象导航到关联的Customer对象Customer customer=order.getCustomer();在Order类中,用@ManyToOne注解映射customer属性: @ManyToOne(targetEntity =Customer.class) @JoinColumn(name="CU原创 2021-05-04 13:13:13 · 341 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:比较JPA的EntityManager接口与Hibernate的Session接口
本文对JPA的EntityManager接口与Hibernate的Session接口进行了比较,本文参考《精通JPA与Hibernate:Java对象持久化技术详解》,作者:孙卫琴。EntityManager接口与Session接口的许多功能很相似,以下表对这两个接口的方法做了对比。从以上表可以看出,EntityManager接口中的大部分方法在Sesson接口中都有对应的方法。EntityManager的remove()方法与Session的delete()方法的作用基本上相同,两者的一个小小区别是原创 2021-05-04 13:01:07 · 561 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:映射对象标识符的基本原理
Java语言按内存地址来识别或区分同一个类的不同对象,而关系数据库按主键值来识别或区分同一个表的不同记录。Hibernate使用OID来统一两者之间的矛盾,OID是关系数据库中的主键(通常为代理主键)在Java对象模型中的等价物。在运行时,Hibernate根据OID来维持Java对象和数据库表中记录的对应关系。例如:Transaction tx = session.beginTransaction(); Customer c1=session.get(Customer.class, Long.va原创 2021-05-04 12:50:01 · 316 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:用@MapsId注解映射派生主键
假定Person类和PersonDetail类为一对一关联关系,相应的,PERSONS表和PERSON_DETAILS表为一对一参照关系。PERSON_DETAILS表的ID字段既是主键,又作为外键参照PERSONS表的ID主键,因此,PERSON_DETAILS表的ID主键实际上来自于PERSONS表的ID主键。PERSON_DETAILS表的ID主键称为派生主键。Person类的定义如下:@Entity@Table(name="PERSONS")public static class Perso原创 2021-05-04 12:41:44 · 670 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:用@Formula注解映射派生属性
并不是持久化类的所有属性都直接和表的字段匹配,持久化类的有些属性的值必须在运行时通过计算才能得出来,这种属性称为派生属性。下面介绍利用Hibernate的@Formula注解来映射派生属性。@Formula注解用来设置一个SQL表达式,Hibernate将根据它来计算出派生属性的值。下面以Customer类的totalPrice属性为例,介绍@Formula注解的用法。Customer类的totalPrice属性表示客户的所有订单的价格总和,它的取值为与Customer对象关联的所有Order对象的pr原创 2021-05-04 12:31:28 · 301 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:JPA的配置文件
JPA的配置文件名为persistence.xml,位于classpath根目录的META-INF目录下,它的作用和Hibernate的配置文件hibernate.cfg.xml很相似。以下persistence.xml是本范例的JPA配置文件。/** persistence.xml */<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XML原创 2021-05-04 12:25:06 · 394 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:从JPA API中获得Hibernate API
当JPA API不能满足所有的应用需求,还可以利用Hibernate API来辅助完成个别功能。JPA API的EntityManager接口和EntityManagerFactory接口都有一个unwrap()方法,它们分别返回相应的Session以及SessionFactory对象://获得Hibernate API中的SessionFactory SessionFactory sessionFactory = entityManagerFactor.unwrap( Sessi原创 2021-05-04 12:17:41 · 266 阅读 · 0 评论 -
孙卫琴的《精通JPA与Hibernate》源代码下载
孙卫琴的《精通JPA与Hibernate》的源代码下载原创 2021-04-30 18:13:13 · 497 阅读 · 1 评论 -
孙卫琴的《精通JPA与Hibernate》的读书笔记:持久化层对象的四种状态
站在持久化层的角度,一个Java对象在它的生命周期中,可处于以下四个状态之一:(1) 临时状态(transient):刚用new语句创建,还没有被持久化,并且不处于持久(2) 化缓存中。处于临时状态的Java对象被称为临时对象。(3) 持久化状态(persistent):已经被持久化,并且加入到持久化缓存中。处于持久化状态的Java对象被称为持久化对象。(4) 删除状态(removed):不再处于持久化缓存中,并且Session已经计划将其从数据库中删除。处于删除状态的Java对象被称为被删除对象.原创 2021-04-30 18:04:23 · 398 阅读 · 1 评论 -
孙卫琴的《精通JPA与Hibernate》读书笔记:@Enumerated注解映射枚举类型
以下代码定义了一个表示性别类的Gender枚举类型:public class Gender extends Enum{ public static final Gender FEMALE; public static final Gender MALE;}假定Customer类有一个表示性别的gender属性,它是Gender枚举类型:@Column(name="GENDER")private Gender gender=Gender.MALE;默认情况下,Hibernate会把枚举原创 2021-04-30 17:57:30 · 308 阅读 · 1 评论 -
孙卫琴的《精通JPA与Hibernate》读书笔记:@Access注解设定Hibernate访问类的属性的方式
持久化层访问持久化类的属性主要有两种方式:(1) property访问方式:表明Hibernate通过相应的setXXX()和getXXX()方法来访问类的属性。这是优先推荐的方式,为持久化类的每个属性提供setXXX()和getXXX()方法,可以更灵活地封装持久化类,提高域模型的透明性。(2) field访问方式:表明Hibernate直接访问类的属性。在持久化类中,可以通过@Access注解来设定Hibernate访问持久化类的属性的方式,例如://设定property访问方式@Access原创 2021-04-30 17:50:26 · 483 阅读 · 1 评论 -
孙卫琴的《精通JPA与Hibernate》读书笔记:Hibernate的配置文件
在Hibernate的配置文件中,需要指定连接数据库的信息,包括数据库URL,用户名和口令,JDBC驱动程序等。hibernate.cfg.xml<hibernate-configuration> <session-factory > <property name="dialect"> org.hibernate.dialect.MySQL8Dialect </property> <property name原创 2021-04-30 17:43:40 · 300 阅读 · 1 评论