#
1.JPA和Hibernate的关系
1.1 JPA的供应商
1.2 JPA的优势
1.3 JPA 包含三方面的技术
2.Holle Word
2.1 使用JPA持久化对象的步骤
创建 persistence.xml, 在这个文件中配置持久化单元
------需要指定跟哪个数据库进行交互;
------需要指定 JPA 使用哪个持久化的框架以及配置该框架的基本属性
2.2创建实体类, 使用 annotation 来描述实体类跟数据库表之间的映射关系.
使用 JPA API 完成数据增加、删除、修改和查询操作
2.3创建 EntityManagerFactory (对应 Hibernate 中的 SessionFactory);
2.4创建 EntityManager (对应 Hibernate 中的Session);
2.5 在Eclipse下创建JPA工程
2.5.1创建jpa项目
2.5.2 JPA版本选择2.0
2.5.3 ![aa](https://i-blog.csdnimg.cn/blog_migrate/e3f7f21bd8dc0337db4723ba7cbfdcad.png)
3. JPA基本注解
@Entity
标注用于实体类声明语句之前,指出该Java 类为实体类,将映射到指定的数据库表。如声明一个实体类 Customer,它将映射到数据库中的 customer 表上。
@Table
当实体类与其映射的数据库表名不同名时需要使用 @Table 标注说明,该标注与 @Entity 标注并列使用,置于实体类声明语句之前,可写于单独语句行,也可与声明语句同行。
@Table 标注的常用选项是 name,用于指明数据库的表名
@Table标注还有一个两个选项 catalog 和 schema 用于设置表所属的数据库目录或模式,通常为数据库名。uniqueConstraints 选项用于设置约束条件,通常不须设置。
@Id
@Id 标注用于声明一个实体类的属性映射为数据库的主键列。该属性通常置于属性声明语句之前,可与声明语句同行,也可写在单独行上。
@Id标注也可置于属性的getter方法之前。
@GeneratedValue
@GeneratedValue 用于标注主键的生成策略,通过 strategy 属性指定。默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:SqlServer 对应 identity,MySQL 对应 auto increment。
在 javax.persistence.GenerationType 中定义了以下几种可供选择的策略:
@Basic
1.@Basic 表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的 getXxxx() 方法,默认即为
2.fetch: 表示该属性的读取策略,有 EAGER 和 LAZY 两种,分别表示主支抓取和延迟加载,默认为 EAGER.
3.optional:表示该属性是否允许为null, 默认为true
@Column
当实体的属性与其映射的数据库表的列不同名时需要使用
@Column 标注说明,该属性通常置于实体的属性声明语句之前,还可与 @Id 标注一起使用。
@Column 标注的常用属性是 name,用于设置映射数据库表的列名。此外,该标注还包含其它多个属性,如:unique 、nullable、length 等。
@Column 标注的 columnDefinition 属性: 表示该字段在数据库中的实际类型.通常 ORM 框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是DATE,TIME还是TIMESTAMP.此外,String的默认映射类型为VARCHAR, 如果要将 String 类型映射到特定数据库的 BLOB 或TEXT 字段类型.
@Column标注也可置于属性的getter方法之前
@Transient
1.表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性.
2.如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient
否则,ORM框架默认其注解为@Basic
@Temporal
在核心的 Java API 中并没有定义 Date 类型的精度(temporal precision). 而在数据库中,表示 Date 类型的数据有 DATE, TIME, 和 TIMESTAMP 三种精度(即单纯的日期,时间,或者两者 兼备). 在进行属性映射时可使用@Temporal注解来调整精度.
加粗样式在这里插入图片描述
4. JPA API
1.Persistence 类是用于获取 EntityManagerFactory 实例。该类包含一个名为 createEntityManagerFactory 的静态方法 。
2.createEntityManagerFactory 方法有如下两个重载版本。
带有一个参数的方法以 JPA 配置文件 persistence.xml 中的持久化单元名为参数
带有两个参数的方法:前一个参数含义相同,后一个参数 Map类型,用于设置 JPA 的相关属性,这时将忽略其它地方设置的属性。Map 对象的属性名必须是 JPA 实现库提供商的名字空间约定的属性名。
1.EntityManagerFactory 接口主要用来创建 EntityManager 实例。该接口约定了如下4个方法:
createEntityManager():用于创建实体管理器对象实例。
createEntityManager(Map map):用于创建实体管理器对象实例的重载方法,Map 参数用于提供 EntityManager 的属性。
isOpen():检查 EntityManagerFactory 是否处于打开状态。实体管理器工厂创建后一直处于打开状态,除非调用close()方法将其关闭。
close():关闭 EntityManagerFactory 。 EntityManagerFactory 关闭后将释放所有资源,isOpen()方法测试将返回 false,其它方法将不能调用,否则将导致IllegalStateException异常。
1.在 JPA 规范中, EntityManager 是完成持久化操作的核心对象。实体作为普通 Java 对象,只有在调用 EntityManager 将其持久化后才会变成持久化对象。EntityManager 对象在一组实体类与底层数据源之间进行 O/R 映射的管理。它可以用来管理和更新 Entity Bean, 根椐主键查找 Entity Bean, 还可以通过JPQL语句查询实体。
2 .实体的状态:
新建状态: 新创建的对象,尚未拥有持久性主键。
持久化状态:已经拥有持久性主键并和持久化建立了上下文环境
游离状态:拥有持久化主键,但是没有与持久化建立上下文环境
删除状态: 拥有持久化主键,已经和持久化建立上下文环境,但是从数据库中删除。
3.find (Class entityClass,Object primaryKey):返回指定的 OID 对应的实体类对象,如果这个实体存在于当前的持久化环境,则返回一个被缓存的对象;否则会创建一个新的 Entity, 并加载数据库中相关信息;若 OID 不存在于数据库中,则返回一个 null。第一个参数为被查询的实体类类型,第二个参数为待查找实体的主键值。
4.getReference (Class entityClass,Object primaryKey):与find()方法类似,不同的是:如果缓存中不存在指定的 Entity, EntityManager 会创建一个 Entity 类的代理,但是不会立即加载数据库中的信息,只有第一次真正使用此 Entity 的属性才加载,所以如果此 OID 在数据库不存在,getReference() 不会返回 null 值, 而是抛出EntityNotFoundException
5. persist (Object entity):用于将新创建的 Entity 纳入到 EntityManager 的管理。该方法执行后,传入 persist() 方法的 Entity 对象转换成持久化状态。
如果传入 persist() 方法的 Entity 对象已经处于持久化状态,则 persist() 方法什么都不做。
如果对删除状态的 Entity 进行 persist() 操作,会转换为持久化状态。
如果对游离状态的实体执行 persist() 操作,可能会在 persist() 方法抛出 EntityExistException(也有可能是在flush或事务提交后抛出)。
6.remove (Object entity):删除实例。如果实例是被管理的,即与数据库实体记录关联,则同时会删除关联的数据库记录。
7.merge (T entity):merge() 用于处理 Entity 的同步。即数据库的插入和更新操作
7.flush ():同步持久上下文环境,即将持久上下文环境的所有未保存实体的状态信息保存到数据库中。
8.setFlushMode (FlushModeType flushMode):设置持久上下文环境的Flush模式。参数可以取2个枚举
—FlushModeType.AUTO 为自动更新数据库实体,
—FlushModeType.COMMIT 为直到提交事务时才更新数据库记录。
9.getFlushMode ():获取持久上下文环境的Flush模式。返回FlushModeType类的枚举值。
10.refresh (Object entity):用数据库实体记录的值更新实体对象的状态,即更新实例的属性值。
11.clear ():清除持久上下文环境,断开所有关联的实体。如果这时还有未提交的更新则会被撤消。
12.contains (Object entity):判断一个实例是否属于当前持久上下文环境管理的实体。
13.isOpen ():判断当前的实体管理器是否是打开状态。
14.getTransaction ():返回资源层的事务对象。EntityTransaction实例可以用于开始和提交多个事务。
15.close ():关闭实体管理器。之后若调用实体管理器实例的方法或其派生的查询对象的方法都将抛出 IllegalstateException 异常,除了getTransaction 和 isOpen方法(返回 false)。不过,当与实体管理器关联的事务处于活动状态时,调用 close 方法后持久上下文将仍处于被管理状态,直到事务完成。
16.createQuery (String qlString):创建一个查询对象。
17.createNamedQuery (String name):根据命名的查询语句块创建查询对象。参数为命名的查询语句。
18.createNativeQuery (String sqlString):使用标准 SQL语句创建查询对象。参数为标准SQL语句字符串。
19.createNativeQuery (String sqls, String resultSetMapping):使用标准SQL语句创建查询对象,并指定返回结果集 Map的 名称。
20.EntityTransaction 接口用来管理资源层实体管理器的事务操作。通过调用实体管理器的getTransaction方法 获得其实例。
1.begin ()
-------用于启动一个事务,此后的多个数据库操作将作为整体被提交或撤消。若这时事务已启动则会抛出 ------------IllegalStateException 异常。
2.commit ()
-------用于提交当前事务。即将事务启动以后的所有数据库更新操作持久化至数据库中。
3.rollback ()
-------撤消(回滚)当前事务。即撤消事务启动后的所有数据库更新操作,从而不对数据库产生影响。
4.setRollbackOnly ()
-------使当前事务只能被撤消。
5.getRollbackOnly ()
-------查看当前事务是否设置了只能撤消标志。
6.isActive ()
查看当前事务是否是活动的。如果返回true则不能调用begin方法,否则将抛出 IllegalStateException 异常;如果返回 false 则不能调用 commit、rollback、setRollbackOnly 及 getRollbackOnly 方法,否则将抛出 IllegalStateException 异常。
5. 映射关联关系
5.1.双向一对多及多对一映射
5.2双向一对一映射
5.3 双向 1-1 不延迟加载的问题
5.4 双向多对多关联关系
6.使用二级缓存
6.1.创建 ehcache.xml文件
<ehcache>
<!--磁盘存储:将缓存中暂时不使用的对象,转移到硬盘,类似于Windows系统的虚拟内存-->
<!--path:指定在硬盘上存储对象的路径-->
<!--java.io.tmpdir 是默认的临时文件路径。 可以通过如下方式打印出具体的文件路径System.out.println(System.getProperty("java.io.tmpdir"));-->
<!-- 指定二级缓存存放在磁盘上的位置,可以使用磁盘目录,也可以使用Java System Property目录,-->
<!--user.home是用户目录、user.dir是用户当前工作目录、java.io.tmpdir是默认临时文件路径-->
<diskStore path="java.io.tmpdir"/>
<!--defaultCache:默认的管理策略-->
<!--eternal:设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要
根据timeToIdleSeconds,timeToLiveSeconds判断-->
<!--maxElementsInMemory:在内存中缓存的element的最大数目-->
<!--overflowToDisk:如果内存中数据超过内存限制,是否要缓存到磁盘上-->
<!--diskPersistent:是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false-->
<!--timeToIdleSeconds:对象空闲时间(单位:秒),指对象在多长时间没有被访问就会失效。只对eternal为
false的有效。默认值0,表示一直可以访问-->
<!--timeToLiveSeconds:对象存活时间(单位:秒),指对象从创建到失效所需要的时间。只对eternal为false的
有效。默认值0,表示一直可以访问-->
<!--memoryStoreEvictionPolicy:缓存的3 种清空策略-->
<!--FIFO:first in first out (先进先出)-->
<!--LFU:Less Frequently Used (最少使用).意思是一直以来最少被使用的。缓存的元素有一个hit 属性,hit
值最小的将会被清出缓存-->
<!--LRU:Least Recently Used(最近最少使用). (ehcache 默认值).缓存的元素有一个时间戳,当缓存容量满
了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存-->
<!-- Sets the path to the directory where cache .data files are created.
If the path is a Java System Property it is replaced by
its value in the running VM.
The following properties are translated:
user.home - User's home directory
user.dir - User's current working directory
java.io.tmpdir - Default temp file path -->
<diskStore path="java.io.tmpdir"/>
<!--Default Cache configuration. These will applied to caches programmatically created through
the CacheManager.
The following attributes are required for defaultCache:
maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit.
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!--Predefined caches. Add your cache configuration settings here.
If you do not have a configuration for your cache a WARNING will be issued when the
CacheManager starts
The following attributes are required for defaultCache:
name - Sets the name of the cache. This is used to identify the cache. It must be unique.
maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit.
-->
<!-- Sample cache named sampleCache1
This cache contains a maximum in memory of 10000 elements, and will expire
an element if it is idle for more than 5 minutes and lives for more than
10 minutes.
If there are more than 10000 elements it will overflow to the
disk cache, which in this configuration will go to wherever java.io.tmp is
defined on your system. On a standard Linux system this will be /tmp"
-->
<cache name="sampleCache1"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<!-- Sample cache named sampleCache2
This cache contains 1000 elements. Elements will always be held in memory.
They are not expired. -->
<cache name="sampleCache2"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/> -->
<!-- Place configuration for your caches following -->
</ehcache>
6.2 在persistence.xml文件中添加一下节点
<!-- 配置二级缓存的策略 -->
<!--
配置二级缓存的策略
ALL:所有的实体类都被缓存
NONE:所有的实体类都不被缓存.
ENABLE_SELECTIVE:标识 @Cacheable(true) 注解的实体类将被缓存
DISABLE_SELECTIVE:缓存除标识 @Cacheable(false) 以外的所有实体类
UNSPECIFIED:默认值,JPA 产品默认值将被使用
-->
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
小编的persistence.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="jpa-3" transaction-type="RESOURCE_LOCAL">
<!--
配置使用什么 ORM 产品来作为 JPA 的实现
1. 实际上配置的是 javax.persistence.spi.PersistenceProvider 接口的实现类
2. 若 JPA 项目中只有一个 JPA 的实现产品, 则也可以不配置该节点.
-->
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<!-- 配置持久化类 -->
<class>com.zking.model.User</class>
<!-- 配置二级缓存的策略 -->
<!--
配置二级缓存的策略
ALL:所有的实体类都被缓存
NONE:所有的实体类都不被缓存.
ENABLE_SELECTIVE:标识 @Cacheable(true) 注解的实体类将被缓存
DISABLE_SELECTIVE:缓存除标识 @Cacheable(false) 以外的所有实体类
UNSPECIFIED:默认值,JPA 产品默认值将被使用
-->
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<!-- 配置数据源 -->
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="123"/>
<!-- 配置数据库方言 -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<!-- 配置基本信息 -->
<!-- 配置mysql方言 -->
<property name="hibernate.dealect" value="org.hibernate.dialect.MySQLDialect" />
<!-- 配置自动创建数据库表 -->
<property name="hibernate.hbm2ddl.auto" value="update" />
<!-- 显示sql打印 -->
<property name="hibernate.show_sql" value="true" />
<!-- 设置初始化sql语句格式 -->
<property name="hibernate.format_sql" value="true" />
<!-- 启用二级缓存 -->
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
</properties>
</persistence-unit>
</persistence>
7. JPQL语言
1.JPQL语言,即 Java Persistence Query Language 的简称。JPQL 是一种和 SQL 非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库的 SQL 查询,从而屏蔽不同数据库的差异。
2.JPQL语言的语句可以是 select 语句、update 语句或delete语句,它们都通过 Query 接口封装执行
javax.persistence.Query接口
Query接口封装了执行数据库查询的相关方法。调用 EntityManager 的 createQuery、create NamedQuery 及 createNativeQuery 方法可以获得查询对象,进而可调用 Query 接口的相关方法来执行查询操作。
select语句
select语句用于执行查询。其语法可表示为:
select_clause
form_clause
[where_clause]
[groupby_clause]
[having_clause]
[orderby_clause]
select-from 子句
1.from 子句是查询语句的必选子句。
------Select 用来指定查询返回的结果实体或实体的某些属性
2.From 子句声明查询源实体类,并指定标识符变量(相当于SQL表的别名)。
如果不希望返回重复实体,可使用关键字 distinct 修饰。select、from 都是 JPQL 的关键字,通常全大写或全小写,建议不要大小写混用。
7.1使用 Hibernate 的查询缓存
7.2 order by子句
order by子句用于对查询结果集进行排序。和SQL的用法类似,可以用 “asc“ 和 "desc“ 指定升降序。如果不显式注明,默认为升序。
select o from Orders o order by o.id
select o from Orders o order by o.address.streetNumber desc
select o from Orders o order by o.customer asc, o.id desc
7.3 group by子句与聚合查询
group by 子句用于对查询结果分组统计,通常需要使用聚合函数。常用的聚合函数主要有 AVG、SUM、COUNT、MAX、MIN 等,它们的含义与SQL相同。例如:select max(o.id) from Orders o
//没有 group by 子句的查询是基于整个实体类的,使用聚合函数将返回单个结果值,可以使用Query.getSingleResult()得到查询结果。例如:
Query query = entityManager.createQuery(
"select max(o.id) from Orders o");
Object result = query.getSingleResult();
Long max = (Long)result;
7.4 having 子句
Having 子句用于对 group by 分组设置约束条件,用法与where 子句基本相同,不同是 where 子句作用于基表或视图,以便从中选择满足条件的记录;having 子句则作用于分组,用于选择满足条件的组,其条件表达式中通常会使用聚合函数。
例如,以下语句用于查询订购总数大于100的商家所售商品及数量:
select o.seller, o.goodId, sum(o.amount) from V_Orders o group by
o.seller, o.goodId having sum(o.amount) > 100
having子句与where子句一样都可以使用参数。
8.关联查询
1.在JPQL中,很多时候都是通过在实体类中配置实体关联的类属性来实现隐含的关联(join)查询。例如:
select o from Orders o where o.address.streetNumber=2000
2.上述JPQL语句编译成以下SQL时就会自动包含关联,默认为左关联。
3.在某些情况下可能仍然需要对关联做精确的控制。为此,JPQL 也支持和 SQL 中类似的关联语法。如:
------left out join / left join
------inner join
------left join / inner join fetch
------其中,left join和left out join等义,都是允许符合条件的右边表达式中的实体为空。
4.例如,以下外关联查询可以找出所有客户实体记录,即使它未曾订货:
select c from Customers c left join c.orders o
5.以下内关联查询只找出所有曾订过商品的客户实体记录:
select c from Customers c inner join c.orders o
6.如果001号客户下过5次订单的话,以下fetch关联查询将得到 5个客户实体的引用,并且执行了 5 个订单的查询:
select c from Customers c left join fetch c.orders o where c.id=001
9.子查询
JPQL也支持子查询,在 where 或 having 子句中可以包含另一个查询。当子查询返回多于 1 个结果集时,它常出现在 any、all、exist s表达式中用于集合匹配查询。它们的用法与SQL语句基本相同。
10. JPQL函数![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/4994b0500e20cac67a049035d282f51e.png)
11.UPDATE 语句
1.update语句用于执行数据更新操作。主要用于针对单个实体类的批量更新
以下语句将帐户余额不足万元的客户状态设置为未偿付:
update Customers c set c.status = '未偿付' where c.balance <
10000
12DELETE 语句
delete语句用于执行数据更新操作。
以下语句删除不活跃的、没有订单的客户:
delete from Customers c where c.status =
'inactive' and c.orders is empty