JavaEE高级-JPA学习笔记

*JPA概述

*JPA是什么?

  - Java Persistence API :用于对象持久化的API

  - Java EE 5.0平台标准的ORM规范,使得应用程序以统一的方式访问持久化层

    

  - JPA是hibernate的一个抽象(就像JDBC和JDBC驱动的关系):

    > JPA是规范:JPA本质上就是一种ORM规范,不是ORM框架---因为JPA并为提供ORM实现,它只是制定了一些规范,提供了一些编程的API接口,但具体实现则由ORM厂商提供实现

    > Hibernate是实现:Hibernate除了作为ORM框架之外,它也是一种JPA实现

  - 从功能上来说,JPA是Hibernate功能的一个子集

  - JPA的优势:

    > 标准化:提供相同的API,这保证了基于JPA开发的企业应用能够经过少量的修改就可以在不同的JPA框架下运行

    > 简单易用,集成方便:JPA的主要目标之一就是提供更加简单的编程模型,在JPA框架下创建实体和创建Java类一样简单,只需要使用javax.persistence.Entity进行注释;JPA的框架和接口也都非常简单

    > 可以媲美JDBC的查询能力:JPA的查询语言是面向对象的、JPA定义了独特的JPQL,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING等通常只有SQL才能够提供的高级查询特性,甚至还能够支持子查询

    > 支持面向对象的高级特性:JPA中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系、最大限度的使用面向对象的模型

  - JPA包括3方面的技术

    > ORM映射元数据:JPA支持XML和JDK 5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中。

    > JPA的API:用来操作实体对象,执行CRUD操作,框架在后台完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。

    > 查询语言(JPQL):这是持久化操作中很重要的一个方法,通过面向对象而非面向数据库的查询语言查询数据,避免程序和具体的SQL紧密耦合

 

*JPA基本注解

  - @Entity:用于标注实体类声明语句之前,之处该java类为实体类,将映射到指定的数据库表。如声明一个实体类Customer,它将映射到数据库中的customer表上

  - @Table:1). 当实体类与其映射的数据库表表名不同时需要使用@Table标注说明,该标注与@Entity标注并列使用,置于实体类声明语句之前,可写于单独语句行,也可与声明语句同行

        2). @Table标注的常用选项是name,用于指明数据库的表名

        3). @Table标注还有一个两个选项catalog和schema用于设置表所属的数据库目录或模式,通常为数据库名。uniqueConstraints选项用于设置约束条件,通常不须设置

  - @Id:1). 用于声明一个实体类的属性映射为数据库的主键列。该属性通常置于属性声明语句之前,可与声明语句同行,也可写在单独行上。

      2). @Id标注也可置于属性的getter方法之前

  - @GeneratedValue:1). 用于标注主键的生成策略,通过strategy属性指定。默认情况下,JPA自动选择一个最适合底层数据库的主键生成策略:SqlServer对应identity,MySQL对应auto increment

            2). 在javax.persistence.GenerationType中定义了以下几种可供选择的策略:

              - IDENTITY:采用数据库ID自增长的方式来自增主键字段,Oracle不支持这种方式

              - AUTO:JPA自动选择合适的策略,是默认选项

              - SEQUENCE:通过序列产生主键,通过@SequenceGenerator注解指定序列名,MySQL不支持这种方式

              - TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。

  - @Basic:1). 表示一个简单的属性到数据库表的字段的映射,对于没有任何标注的getXxxx()方法,默认即为@Basic

        2). fetch:表示该属性的读取策略,有EAGER和LAZY两种,分别表示主支抓取和延迟加载,默认为EAGER

        3). optional:表示该属性是否允许为null,默认为true

  - @Column:1). 当实体的属性与其映射的数据库表的列不同名时需要使用@Column标注说明,该属性通常置于实体的属性声明语句之前,还可与@Id标注一起使用

        2). @Column标注的常用属性是name,用于设置映射数据库表的列名。此外,该标注还包括其它多个属性,如:unique、nullable、length等

        3). @Column标注的columnDefinition属性:表示该字段在数据库中的实际类型. 通常ORM框架可以根据属性类型自动判断数据库中字段的类型,但是对于Date类型仍无法确定数据库中字段类型究竟是DATE,

          TIME还是TIMESTAMP. 此外,String的默认映射类型为VARCHAR,如果要将String类型映射到特定数据库的BLOB或TEXT字段类型

        4). @Column标注也可置于属性的getter()方法之前

  - @Transient:1). 表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性

          2). 如果一个属性并非数据库表的字段映射,就务必将其表示为@Transient,否则,ORM框架默认其注解为@Basic

  - @Temporal:1). 在核心的Java API 中并没有定义Date类型的精度(temporal precision). 而在数据库中,表示Date类型的数据有DATE,TIME和TIMESTAMP三种精度. 在进行映射时可以使用@Temporal注解来调整精度

 

*JPA API

  - JPA相关接口/类:Persistence

    > Persistence类是用于获取EntityManagerFactory实例。该类包含一个名为createEntityManagerFactory的静态方法。

    > createEntityManagerFactory方法有如下两个重载版本。

      >> 带有一个参数的方法以JPA配置文件persistence.xml中的持久化单元名为参数

      >> 带有两个参数的方法:前一个参数含义相同,后一个参数Map,用于设置JPA的相关属性,这时将忽略其它地方设置的属性。Map对象的属性名必须是JPA实现库提供商的名字空间约定的属性名

  - EntityManagerFactory

    > EntityManagerFactory接口主要用来创建EntityManager实例。该接口定义了如下4个方法:

      >> createEntityManager():用于创建实体管理器对象实例。

      >> createEntityManager(Map map):用于创建实体管理器对象实例的重载方法,Map参数用于提供EntityManager的属性

      >> isOpen():检查EntityManagerFactory是否处于打开状态。实体管理器工厂创建后一直处于打开状态,除非调用close()方法将其关闭

      >> close():关闭EntityManagerFactory。EntityManagerFactory关闭后将释放所有资源,isOpen()方法测试将返回false,其它方法将不能调用,否则将导致IllegalStateException异常

  - EntityManager

    > find(Class<T> entityClass,Object primaryKey):返回指定的OID对应的实体类对象,如果这个实体存在于当前的持久化环境,则返回一个被缓存的对象;否则会创建一个新的Entity,

      并加载数据库中相关信息;若OID不存在于数据库中,则返回一个null。第一个参数为被查询的实体类类型,第二个参数为带查询实体的主键值  

    > getReference(Class<T> entityClass,Object primaryKey)与find()方法类似,不同的是:如果缓存中不存在指定的Entity,EntityManager会创建一个Entity类的代理,但是不会立即加载数据库

      中的信息,只有第一次真正使用此Entity的属性才加载,所以若此OID在数据库中不存在,getReference()不会返回null值,而是抛出EntityNotFoundException

    > persist(Object entity):用于将新建的Entity纳入奥EntityManager的管理。该方法执行后,传入persist()方法的Entity对象转换成持久化状态。

      >> 如果传入persist()方法的Entity对象已经处于持久化状态,则persist()方法什么都不做

      >> 如果对删除状态的Entity进行persist()操作,会转换为持久化状态。

      >> 如果对游离对象的实体执行persist()操作,可能会在persist()方法抛出EntityExistException(也有可能是在flush或事务提交后抛出)

    > remove(Object entity):删除实例。如果实例是被管理的,即与数据库实体关联,则会同时删除关联的数据库记录

    > merge(T entiry):用于处理Entity的同步。即数据库的插入和更新操作

       

    > flush():同步持久化上下文环境,即将持久化上下文环境的所有未保存实体的状态信息保存到数据库中

    > setFlushMode(FlushModeType flushMode):设置持久上下文环境的Flush模式。参数可以取2个枚举:

      >> 1). FlushModeType.AUTO为自动更新数据库实体,

      >> 2). FlushModeType.COMMIT为直到提交事务时才更新数据库记录。

    > getFlushMode():获取持久化上下文环境的Flush模式。返回FlushModeType类的枚举值

    > refresh(Object entity):用数据库实体记录的值更新实体对象的状态,即更新实例的属性值

    > clear():清除持久化上下文环境,断开所有关联的实体。如果这时还有未提交的更新则会被撤销。

    > contains(Object entity):判断一个实例是否属于当前持久化上下文环境管理的实体

    > isOpen():判断当前的实体管理器是否是打开状态。

    > getTransaction():返回资源层的事务对象。EntityTransaction实例可以用于开始和提交多个事务。

    > close():关闭实体管理器。之后若调用实体管理器实例的方法或其派生的查询对象的方法都将抛出IllegalstateException异常,除了getTransaction和isOpen方法(返回false)。不过,

          当与实体管理器关联的事务处于活动状态时,调用close方法后持久化上下文将仍处于被管理状态,直到事务完成。

    > createQuery(String qlString):创建一个查询对象

    > createNamedQuery(String name):根据命名的查询语句块创建查询对象。参数为命名的查询语句。

    > createNativeQuery(String sqlString):使用标准SQL语句创建查询对象。参数为标准SQL语句字符串。

    > createNativeQuery(String slqs,String resultSetMapping):使用标准SQL语句创建查询对象,并指定返回结果集Map的名称。

  - EntityTransaction: EntityTransaction接口用来管理资源层实体管理器的事务操作。通过调用实体管理器的getTransaction方法获得其实例。

    > begin():用于启动一个事务,此后的多个数据库操作将作为整体被提交或撤销。若这时事务已启动则会抛出IllegalStateException异常。

    > commit():用于提交当前事务。即将事务启动以后的所有数据库更新操作持久化至数据库中。

    > rollback():撤销(回滚)当前事务。即撤销事务启动后的所有数据库更新操作,从而不对数据库产生影响

    > setRollbackOnly():使当前事务只能被撤销。

    > getRollbackOnly():查看当前事务是否设置了只能撤销标志。

    > isActive():查看当前事务是否是活动的,如果返回true则不能调用begin方法,否则将抛出IllegalStateException异常;如果返回false则不能调用commit、rollback、setRollbackOnly及getRollbackOnly方法,

          否则将抛出IllegalStateException异常

 

*映射关联关系

  - 映射单向多对一的关联关系

  - 映射单向一对多的关联关系

  - 映射双向多对一的关联关系

    > 双向一对多关系中,必须存在一个关系维护端,在JPA规范中,要求many的一方作为关系的维护端(owner side),one的一方作为被维护端(inverse side)。

    > 可以在one方指定@OneToMany注释并设置mappedBy属性,以指定它是这一关联中的被维护端,many为维护端。

    > 在many方指定@ManyToOne注释,并使用@JoinColumn指定外键名称

  - 映射双向一对一的关联关系

    > 基本外键的1-1关联关系:在双向的一对一关联中,需要在关系被维护端(inverse side)中的@OneToOne注释中指定mappedBy,以指定是这一关联中的被维护端。

      同时需要在关系维护端(owner side)建立外键列指向关系被维护端的主键列。

    > 双向1-1不延迟加载的问题:

      >> 如果延迟加载要起作用, 就必须设置一个代理对象.

      >> Manager 其实可以不关联一个 Department

      >> 如果有 Department 关联就设置为代理对象而延迟加载, 如果不存在关联的 Department 就设置 null, 因为外键字段是定义在 Department 表中的,Hibernate 在不读取

        Department 表的情况是无法判断是否有关联有 Deparmtment, 因此无法判断设置 null 还是代理对象, 而统一设置为代理对象,也无法满足不关联的情况,所以无法使

        用延迟加载,只 有显式读取 Department.

  - 映射双向多对多的关联关系

    > 在双向多对多关系中,我们必须指定一个关系维护端(owner side),可以通过 @ManyToMany 注释中指定 mappedBy 属性来标识其为关系维护端。

        

 

*使用二级缓存

  - <shared-cache-mode>节点:若JPA实现支持二级缓存,该节点可以配置在当前的持久化单元中是否启用二级缓存,可配置如下值:

    > ALL:所有的实体类都将被缓存

    > NONE:所有的实体类都不被缓存

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

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

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

 

*JPQL

  - JPQL语言,即Java Persistence Query Language的简称。JPQL是一种和SQL非常类似的中间性和对象化查询语言,它最终会被数据库编写成不同的SQL查询语言,从而屏蔽不同数据库之间的差异

  - JPQL可以是select语句,也可以是update语句,或delete语句,它们都通过Query接口封装执行

  - javax.persistence.Query

    > Query接口封装了执行数据库查询的相关方法,调用EntityManager的createQuery、createNamedQuery及createNativeQuery方法可以获得查询对象,进而可调用Query接口的相关方法来执行查询操作

    > Query接口的主要方法:

      >> int executeUpdate():用于执行update或delete语句

      >> List getResultList():用于执行select语句并返回结果集实体列表

      >> Object getSingleResult():用于执行只返回单个结果实体的selete语句

      >> Query setFirstResult(int startPosition):用于设置从哪个实体记录开始返回查询结果

      >> Query setMaxResults(int maxResult):用于设置返回结果实体的最大数。与setFirstResult结合使用可实现分页查询

      >> Query setFlushMode(FlushModeType flushMode):设置查询对象的Flush模式,参数可以取2个枚举值:FlushModeType.AUTO为自动更新数据库记录,FlushMode_Type.COMMIT为直到提交事务时才更新数据库记录

      >> setHint(String hintName,Object value):设置与查询对象相关的特定供应商参数或提示信息。参数名及其取值需要特定JPA实现库提供商的文档。如果第二个参数无效将抛出IIIegalArgumentException异常

      >> setParameter(int position,Object value):为查询语句的指定位置参数赋值。Position指定参数序号,value为赋给参数的值。

      >> setParameter(int position,Date d,TemporalType type):为查询语句的指定位置参数赋Date值。Position指定参数序号,value为赋给参数的值,temporalType取TemporalType的枚举常量,包括DATE、

          TIME及TIMESTAMP三个,用于将Java的Date型值临时转换为数据库支持的日期时间类型(java.sql.Date、java.sql.Time及java.sql.Timestamp)

 

*Spring 整合JPA

  - 三种整合方式:

    > LocalEntityManagerFactoryBean:使用于那些仅使用JPA进行数据访问的项目,该FactoryBean将根据JPA PersistenceProvider自动检查配置文件进行工作,一般从"META-INF/persistence.xml"读取配置信息,

      这种方式最简单但不能设置Spring中定义的DateSource,且不支持Spring管理的全局事务

    > 从JNDI中获取:用于从Java EE 服务器获取指定的EnttityManagerFactory,这种方式在进行Spring事务管理时一般要使用JTA事务管理

    > LocalContainerEntityManagerFactoryBean:适用于所有环境的FactoryBean,能全面控制EntityManagerFactory配置,如指定Spring定义的DateSource等等

 

转载于:https://www.cnblogs.com/LzMingYueShanPao/p/11206614.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值