jpa的认识

JPA-01

  • jpa介绍

1、什么是jpa?

       jpa:Java Persistence API它就是orm的规范(对象关系映射(ORM) 规范

2、jpa与Hibernate的关系

   JPA它是一个orm规范,而hibernate是其最完美的实现,因为JPA和hibernate都是同一个作者

3、jpa与JDBC的优缺点

1.JPA它底层是基于jdbc实现的,它是面向对象的编程,如果你要操作crud,直接调用其api文档传递对象,它会自动生成对应的sql语句

       优点:

          1.操作非常方便

          2.它给我们提供了缓存(1级缓存/2级缓存)

       缺点:因为sql语句是自动生成,所以性能不好控制

       2.JDBC它是操作数据库的唯一技术,它是各大数据库厂商实现的,我们在做crud的时候,必须手动编写sql语句

       优点:性能好控制

       缺点:操作太过于麻烦了

       jdbc和jpa都不适合用于大型项目,只适用于小型项目,中大型项目还是使用mybatis来做

二、jpa程序及配置

     1、使用jpa的步骤

1.导入jar包

                     2.配置jpa的核心文件

                            1).配置持久化单元

                            2).配置jpa的基本属性

                                          1.用户名

                                          2.密码

                                          3.驱动

                                          4.url地址

                                          5.方言

                                          6.是否显示sql语句

                                          7.建表策略

                     3.创建domain

                     4.抽取EntityManagerFactory对象----》因为整个应用系统中,我们只需要一个该对象就可以了

                     核心方法:

                     添加: persist

                     修改: merge

                     删除: remove()只能传递对象

                     查询: find/query

     2、ORM的概念

持久 英文即 persistence。就是把数据保存到可掉电式存储设备中。持久层就是dao层,原来叫数据访问层,现在一般叫持久层,是一个意思

Object Relational Mapping, 对象关系映射框架,ORM 就是通过将Java对象映射到数据库表,通过操作Java对象,就可以完成对数据表的操作

三、jpa的CRUD

     1、提取工具类

public class JPAUtils {

  // 保证EntityManagerFactory是单例

    private static EntityManagerFactory entityManagerFactory;

    static {

    try {

      // 对应配置文件里面的persistence-unit name="cn.itsource.jpa"

     entityManagerFactory = Persistence.createEntityManagerFactory("cn.itsource.jpa");

    } catch (Exception e) {

     e.printStackTrace();

     throw new RuntimeException("解析配置文件或者映射配置出现异常:" + e.getMessage());

    }

  }

  public static EntityManager getEntityManager() {

    return entityManagerFactory.createEntityManager();

  }

}

     2、jpa里面的CRUD方法

1.persist持久化方法,保存方法

      2.merge方法,修改,必须要有id值

3.remove方法,删除,必须要有id值,先从数据库查出来,还要判断这个对象是否为空

4.查询方法可以不要事务,提高性能

5.find方法,通过主键获取domain对象,传入的参数一定要和domain的id的类型匹配

6.jpql是JPA的查询语言,hql是hibernate的查询语言

                    jpql:不能出现表名,列名,*,只能是Java的类名,属性名,别名

                    如果在jpql出现的sql关键字,大小写不敏感,Java的类名,属性名,别名大小写敏感

     3、jpa的建表策略

                     1.create: 先删除表,再创建表     使用场景: 测试阶段,学习阶段

                     2.create-drop: 先删除表,再创建表,再删除表(EntityManagerFactory要关闭)  使用场景: 测试阶段,学习阶段

                     3.update: 只增不减(使用场景:真实开发就用它)

       4.validate:校验,检查domain中的字段和表中的列是否对应的(个数,类型,名字)  校验标准是根据domain来判断的(使用场景:别人把表给你创建好了,你要根据表生成对应的domain)

四、jpa的核心对象

     1、Persistence

主要负责创建EntityManagerFactory对象

     2、EntityManagerFactory

它是一个重量级对象

                                   1.二级缓存

                                   2.连接池

                                   3.管理着所有的doamin

                                   4.解析xml,把xml里面的值都放到EntityManagerFactory中

                                   5.它存储预定义jpql语句

              使用EntityManagerFactory的规则,遵循1:1:1  1个项目对应一个EntityManagerFactory对应1个数据库   

              EntityManagerFactory的生命周期: 随着tomcat的启动而创建,tomcat关闭而销毁  EntityManagerFactory是线程安全的

     3、EntityManager

它是一个轻量级对象

                                   1.一级缓存

                                   2.连接对象

              EntityManager的生命周期: 应该随着你的访问而创建,访问结束之后再销毁  EntityManager是线程不安全的

     4、Transactions事务对象

在同一个EnittyManager中拿到都是同一个事务对象

五、缓存

     1、一级缓存

              EntityManager的一级缓存

       查询对象执行的原理: 通过oid在一级缓存中去查询对应的对象,如果没找到,则发送sql语句到数据库中进行查找,它会把查找的对象放到一级缓存中

              如果在一级缓存中找到了,直接引用

              一级缓存命中的条件

                     1.同一个oid

                     2.同一个EntityManager

                     3.同一个EntityManagerFactory

 

JPA-02

1、主键生成策略

1、主键介绍

       主键是关系数据库中的一个基本概念,它用来保证记录的唯一性。简单来说,就是同一张数据库表中,不允许存在多条相同主键的记录

2、主键策略:

1、identity策略

表示主键自增(真实开发不用它,因为它兼容性不好)只是某些数据库支持   MySQL, SQL Server, DB2, Derby, Sybase, PostgreSQL   MYSQL(推荐使用)
2、sequence策略

mysql是不支持的  但是ORACLE推荐使用(真实开发也不用它,因为兼容性不是特别好)
3、auto策略(默认就是它

以后开发我们就用它,它会根据你当前数据库的方言来判断我应该使用identity策略还是sequence策略
4、table策略

实际开发不用它,因为性能太差了

优点:市场上所有的数据库都支持

特点: 它会单独创建一张表来维护主键

2、JPA持久对象的状态

1、为什么要学习状态?

学习状态的目的是让我们更好的分析jpa执行的顺序与流程,如果你没有学习状态,在你使用jpa的时候
你不好控制它的性能,你会觉得jpa很难用,而且会出现很多情况你解释不了

2、JPA提供了四种状态

1. 临时状态/瞬时状态:  对象new出来之后,还没有和entityManager产生关系的时候
2. 持久化状态/托管状态:该对象和entityManager产生了关系-----》它就会成为一个持久化状态(该对象必定有主键id)
3. 游离状态/脱管状态: 当entityManager关闭资源的时候,该对象就成为一个游离状态
4. 删除状态(JPA特有的): 当entityManager.remove()之后,该对象就是一个删除状态

3、脏数据更新

一个持久状态对象在事务管理内,如果改变原来的数据(非主键),此时出现脏数据,在事务提交的时候自动发出update语句去修改。

4、执行流程分析

   第一步:拿到entityManager,开启事务

第二步:通过entityManager拿到一个对象,那么现在这个对象就是持久化的对象,这个对象会放到一级缓存里面,JPA会为当前这个对象准备一个快照(把这个对象进行了备份)

第三步:提交事务

它会把快照 与 你现在这个对象的数据进行对比,如果相同,就不需要修改,也不会发送SQL(性能就高了)

当不相同的时候,JPA就会认为现在这个数据是脏数据

脏数据它就会在事务提交的时候,把它进行数据库的同步(发送update SQL语句)

5、删除状态是JPA特有的

6、持久对象(domain层)定义规则:

1.类不能定义为final类,因为domain类需要被继承的,否则延迟加载会失效

2.所有属性的类型都必须是包装类型

3.不能是8个基本类型

(int,byte,short,long,char,boolean,float,double)

因为JPA内部代码很多判断都是基于是否等于null

4.必须有默认无参构造方法

因为find方法获取的时候会在内存实例化domain对象,否则报org.hibernate.InstantiationException: No default constructor for entity异常

7、entityManager的方法改变持久对象的状态

3、域对象(domain对象)之间的关系

1、依赖关系

JavaBean之间的依赖关系

分层:表现层,业务层,持久层(依赖关系)

依赖:一般指controll,service,dao层之间的关系

类之间访问关系。无需定义成属性。在A中访问B中的方法或属性,或者A负责实例化B。

xxxService{

       IXxxDao xxxDao = new XxxDaoImpl();//原来

 

使用Spring之后,通过set方法依赖注入xxxDao的实例

(对象实例化交给spring完成)

     IXxxDao xxxDao ;

       public void setXxxDao(IXxxDao xxxDao){

           this.xxxDao=xxxDao;

       }

}

Controller表现层依赖于Service业务层,Service依赖于Dao持久层

2、关联关系

类之间的引用关系,以属性定义的方式表现。

关联按照多重性可分为一对一、一对多、多对一和多对多。 主要指的数据库(类)的关系

按照导航性可分为单向关联和双向关联。

主要指的java类的导航,导航可以从一个类获取另一个的类的实例

员工和部门是什么关系? 多个员工对应一个部门  多对一

一个类的对象与它的属性之间的关系

-------------------------------------------------------------------------

注意:关系的判定一定要根据一般的情况,而不是特殊的情况

注:我们讲的是关系是域对象的关系,与数据库无关

一对一 : QQ(主一)与QQ空间(从一),一夫一妻,一个人一个身体证

多对一(反过来就是一对多) :多个员工都是一个老板 , 多把钥匙对于一把锁,一个部门多个员工,一个产品类型有多个产品

多对多:老师与学生,司机与公交车,用户与角色

注意:

不管理一对多,还是多对多(不管它们是双向还是单向),数据库的结构不变(多方有外键)

多对多:必有一张中间表

一对一:设计方案(共享主键,唯一外键),主从关系

 

JPA-03

1、域对象(domain对象)之间的关系(补充)

1、聚合关系(本质还是双向多对一,一对多)

表示整体与部分的关系,整体和部分可以分开单独存在。

电脑(主板,CPU,IO,内存条)

2、组合关系(本质还是聚合关系,双向多对一,一对多)

强聚合关系,整体和部分之间不能分开。如人(头,手),订单模型,超市购物购物清单等等

有的设计,是一定要在强聚合关系下才使用

2、fetch抓取策略

     1、即时加载

              FetchType.EAGER:立即加载,一般情况下的默认值

     2、懒加载

              FetchType.LAZY:延迟加载,需要的时候才发出sql

 

3、二级缓存

1、导包

              添加二级缓存jar文件

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-ehcache</artifactId>
    <version>4.3.8.Final</version>
</dependency>

2、配置

persistence.xml配置

<!-- 启用二级缓存 -->

<property name="hibernate.cache.use_second_level_cache" value="true" />

<!-- 二级缓存的实现类,文档里面的包名有错的 -->

<!-- 错误 org.hibernate.cache.internal.EhCacheRegionFactory -->

<!-- 正确的 org.hibernate.cache.ehcache.EhCacheRegionFactory -->

<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />

<!-- 启用查询缓存 -->

<property name="hibernate.cache.use_query_cache" value="true" />

3、在<properties>上面添加配置二级缓存扫描的策略

<!-- ALL:所有的实体类都被缓存 -->

<!-- NONE:所有的实体类都不被缓存. -->

<!-- ENABLE_SELECTIVE:标识 @Cacheable(true) 注解的实体类将被缓存 -->

<!-- DISABLE_SELECTIVE:缓存除标识 @Cacheable(false) 以外的所有实体类 -->

<!-- UNSPECIFIED:默认值,JPA 产品默认值将被使用 -->

<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>

4、domain类的二级缓存

二级缓存类配置:命中条件:同一个SessionFactory,不同的entityManager,OID相同

// 一条sql

// @Entity

// @Cacheable(true)

// public class Department{

@Test

public void test2() throws Exception {

       EntityManager entityManager = JPAUtils.getEntityManager();

       //先从一级缓存,二级缓存取数据?取不到,发出sql去获取,填充一级缓存,二级缓存

       Department department1 = entityManager.find(Department.class, 1L);

       //先从一级缓存,二级缓存取数据?一级缓存取到了,返回

       Department department2 = entityManager.find(Department.class, 1L);// 一级缓存命中

       entityManager.close();

 

       EntityManager entityManager2 = JPAUtils.getEntityManager();

       //先从一级缓存,二级缓存取数据?一级缓存没有取到,但是二级缓存取到了,返回

       Department department3 = entityManager2.find(Department.class, 1L);// 二级缓存命中

       //先从一级缓存,二级缓存取数据?一级缓存取到了,返回

       Department department4 = entityManager2.find(Department.class, 1L);// 一级缓存命中

       entityManager2.close();

}

}

4、各个关系介绍

1、单向一对多

              注意的点:

                     关联的集合先new出来,方便操作

                     声明必需使用接口

                     判断有没有关系对象,判断集合的size

                     List,Set(区别:List是有序的,Set是去重),组合关系使用List

                     单向的一对多性能太差,尽量不要使用

                     必须配置外键id,否则会多生成一张表,形成多对多的关系

2、单向多对一

              注意的点:

                     配置懒加载 @ManyToOne(fetch=FetchType.LAZY)

                     关联对象不能先new出来

                     判断有没有关系对象:直接判断对象是否为空

                     先保存一方,再保存多方

3、双向一对多/多对一

              注意的点:

                     多对一 + 一对多 = 双向

                     名称必需一致(边外键的列名必需一致,放弃维护后一方不需要加列名)

                     一方放弃着关系的维护 @OneToMany(mappedBy="productDir")

4、多对多

              注意的点:

                     多一张中间表

                     如果是双向的话,保存表名与列名都一致

                     domain的类toString不用加关联的对象,不然在级联删除时会出现递归现象

5、一对一

       注意的点:

              唯一外键一对一(建议使用)

              主表:放弃关系的维护

              从表:关系维护的字段(外键)

              共享主键一对一(不键使用,jpa不支持,hiberante支持)

6、特别注意

       注意:

              1.多方默认就是LAZY

              2.类不要使用final

              3.关联对象在toString不要打印出来

              4.所有属性的类型都必须是包装类型

       在表中:

              1.有外键就是多对一,有外键的这一方就是多方

              2.外键是唯一键就是一对一,有外键的这方就是从表

              3.出来了中间表,就是多对多

7、级联

       1.级联保存:

保存1方的时候,要把多方一并保存(不保证外检有值,但是有个前提:一方必须要关联多方)

        如果外键要有值,多方必须要去关联1方

    2.级联删除:

删除A方的时候,会把A方关联的对象全部删除(但是该功能不能做到,保留一方的同时去删除多方)

        如果开发中你配置了级联删除,你可以配置最强级联

         orphanRemoral=true:孤儿删除,既能保留一方也能删除多方

    3.级联修改:一般不用

 

JPA-04

  1. JPQL

1.JPQL基本格式

              1.只能写java的类名和属性名

SELECT o[o.property,o.property*] FROM Entity o

[WHERE conditions]

类------表

属性-----列名

[GROUP BY conditions]

[HAVING conditions]

[ORDER BY o.property[ASC|DESC]]

2.JPQL本质是JPA通过antlr-2.7.7.jar翻译成sql并且封装执行的

2.JPQL关键点

              1. JPQL和SQL很像,查询关键字都是一样的

              2. 唯一的区别是:JPQL是面向对象的

3.JPQL规则

              1.JPQL两大准则:

                     1、如果要连表查询,不是关联的表,而是关联的属性

                     2、不需要加on,它会自动消除笛卡尔积

              2.需要注意的点:

1.里面不能出现表名,列名,只能出现java的类名,属性名,区分大小写

2.出现的sql关键字是一样的意思,不区分大小写

3.不能写select * 要写select 别名

 

4.JPQL查询

1.简单查询

1.查询所有:String jpql = "FROM Employee";

2.查询特定属性:String jpql = "select o.name,o.depatment FROM Employee o";

3.根据条件查询:String jpql = "from Employee where department.city=? or department.city=?";

4.根据条件排序: "from Employee order by salary desc(dept.cn,相关联类的字段)";//desc是降序排列,默认为升序

5.根据in的条件查询:"from Employee where department.street in(?,?)";//in中的条件可以多个,表示或的意思

6.查询范围:"from Employee where salary between ? and ?";// 相当于  salary>=? and salary<=? 闭区间

              7.模糊查询:"from Employee where name like ? or name like ?";

                                          ?都可以根据方法query.setParameter(1, "%er%").setParameter(2, "%en%")使用

2.去重

distanct:String jpql = "select distinct o.department from Employee o";

3.JPQL集合操作

         

4.JPQL中join操作

      

      

5.JPQL聚集函数

      

6.JPQL分页查询

       1、假分页

      

       2、真分页

      

2、原生SQL用于JPA

      

      

             

      

3、事务并发(乐观锁)

       1.并发问题

              1.第一类数据丢失

              2.第二类数据丢失

              3.脏读

              4.虚读

              5.不可重复读

       2.数据库隔离级别

              MySql默认隔离级别为:Repeatable Read(可能会出现虚读)

Oracle 支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别

   默认隔离级别为READ COMMITTED

READ UNCOMMITTED 幻想读、不可重复读和脏读都允许。

READ COMMITTED 允许幻想读,不可重复读,不允许脏读  只给你处理了脏读(oracle默认隔离级别)

REPEATABLE READ 允许幻想读,不允许不可重复读和脏读(mysql)   它给你处理了不可重复读和脏读

SERIALIZABLE 幻想读、不可重复读和脏读都不允许  把这三个问题都给你处理好了

 

3.悲观锁

       session.get(Product.class, 1L, LockOptions.UPGRADE);一般不使用

       4..乐观锁

              使用版本version,主要用于防止第二类数据丢失

             

      

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值