Hibernate与Jpa的关系(2)
【转自:http://blog.163.com/hero_213/blog/static/398912142010312024809/ 】
近年来ORM(Object-Relational Mapping)对象关系映射,即实体对象和数据库表的映射)技术市场人声音鼎沸,异常热闹, Sun在充分吸收现有的优秀ORM框架设计思想的基础上,制定了新的JPA(Java Persistence API)规范。JPA Java Persistence API,是Java EE 5的标准ORM接口,也是ejb3规范的一部分。
那么什么是JPA呢?JPA是通过JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期实体对象持久化到数据库中去。
Hibernate与JPA的关系及其实现机制
JPA和Hibernate之间的关系,可以简单的理解为JPA是标准接口,Hibernate是实现。那么Hibernate是如何实现与JPA的这种关系的呢。Hibernate主要是通过三个组件来实现的,及hibernate-annotation、hibernate-entitymanager和hibernate-core。
hibernate-annotation是Hibernate支持annotation方式配置的基础,它包括了标准的JPA annotation以及Hibernate自身特殊功能的annotation。
hibernate-core是Hibernate的核心实现,提供了Hibernate所有的核心功能。
hibernate-entitymanager实现了标准的JPA,可以把它看成hibernate-core和JPA之间的适配器,它并不直接提供ORM的功能,而是对hibernate-core进行封装,使得Hibernate符合JPA的规范。
下面重点介绍一下hibernate-entitymanager包的主要类及实现。
HibernatePersistence.java,实现了JPA的PersistenceProvider接口,它提供createEntityManagerFactory和createContainerEntityManagerFactory两个方法来创建EntityManagerFactory对象,这两个方法底层都是调用的EJB3Configuration对象的buildEntityManagerFactory方法,来解析JPA配置文件persistence.xml,,并创建EntityManagerFactory对象。
EntityManagerFactory对象的实现是EntityManagerFactoryImpl类,这个类有一个最重要的*******属性就是Hibernate的核心对象之一SessionFactory。这个类最重要的方法是createEntityManager,来返回EntityMnagaer对象,而sessionFactory属性也传入了该方法。
EntityManager对象的实现是EntityManagerImpl类,这个类继承自AbstractEntityManagerImpl类,在AbstractEntityManager类中有一个抽象方法getSession来获得Hibernate的Session对象,正是在这个Session对象的实际支持下,EntityManagerImpl类实现了JPA的EntityManager接口的所有方法,并完成实际的ORM操作。
此外,hibernate-entitymanager包中还有QueryImpl类利用EntityManagerImpl的支持实现了JPA的Query接口;TransactionImpl利用EntityManagerImpl的支持实现了JPA的EntityTransaction接口。
至此,Hibernate通过hibernate-entitymanager包完成了对于JPA的全部支持工作。
这里我们要先谈一下什么叫实体(Entity),按照JPA规范,具有ORM元数据的领域对象就叫做实体。它应具备一下条件:
1.必须使用javax.persistence.Entity注解或XML映射文件中有对应的<entity>元素;
2.必须具有一个不带参数的构造函数,类不能声明为final,方法和需要持久化的属性也不能声明为final;
3.如果游离态的实体对象需要以值的方式进行传递(如通过Session bean的远程业务接口传递),则必须实现Serializable接口;
4.需要持久化的属性,起访问修饰符不能是public,它必须通过实体类方法进行访问。
实体的状态
实体共有4种状态:
1、 新建态:新创建的实体对象,尚未拥有持久化主键,没有和一个持久化上下文关联起来
2、 受控态:已经拥有持久化主键和持久化上下文建立了联系
3、 游离态:拥有持久化主键,但尚未和持久化上下文建立联系
4、 删除态:拥有持久化主键,已经和持久化上下文建立了联系,但已经被安排从数据库中删除
下面我们来尝试对一个域对象进行JPA注解,使其成为一个实体类:
@Entity(name=”T_TEST”)
public class Test implements Serializable{
@Id
@GeneratedValue(strategy=GenerationType.TABLE)
@Column(name=” id”)
******* int testId;
@Column(name=”uname”,length=100)
******* String uname;
@Column(name=”password”)
******* String password;
@Column(name=”time”)
@Temporal(TemporalType.Date)
******* Date loginTime;
//省略get/setter方法
}
@下面对以上代码中所涉及的JPA注解进行一下说明
@Entity:将领域对象标注为一个实体类,表示该类需要持久化到数据库中,默认情况下类名即表名,通过name属性显式指定表名,如:name=”T_TEST”表示将Test保存到表T_TEST表中。
@Id:对应的属性是表的主键
@GeneratedValue:主键的产生策略,通过strategy属性进行指定,默认情况下,JPA自动选择一个最适合底层数据库的主键生成策略,如SqlServer对应的identity:
mysql对应的auto increment,在java.persistence.GenerationType中定义了几种可以供选择的策略:
1. Identity:表自动增长字段,Oracle不支持这种方式;
2. AUTO:JPA自动选择合适的策略,是默认选项;
3. Sequence:通过序列产生主键,通过@SequenceGenerator注解指定序列名,Mysql不支持这种方式。
4. TABLE:通过表产生主键,框架借由表模拟产生主键,使用该策略可以使用更易于数据库的移植。
@Colunm(name=”uname”):属性对应的表字段。我们并不需要指定表字段的类型,因为JPA 会根据反射从实体属性中获取类型;如果是字符串类型,我们可以指定字段长度,以便可以自动生成DDL语句。
@Temporal(TemporalType.DATE):如果属性是时间类型,因为数据表对时间类型有更严格的划分,所以必须指定具体时间类型,在java.persistence.TemporalType枚举中定义了三种时间类型:
1. Date:等于java.sql.Date;
2. Time:等于java.sql.Time;
3. TimeStamp:等于java.sql.Timestamp。
JPA对于具有父子关系的类,对于父类必须声明继承实体的映射策略,对于继承实体,java.persistence.InheritanceType定义了3种映射策略:
SINGLE_TABLE:父子类都保存在同一个表中,通过字段值进行区分。
JOINED:父子类相同的部分保存在同一个表中,不同的部门分开存放,通过连接不同的表获取完整数据。
TABLE_PER_CLASS:每一个类对应自己的表,一般不推荐采用这种方式。
下面我们来看看实际的列子是怎么运用的。
父类Test
@Entity(name=”test”)
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)//指定继承策略
@DiscriminatorColumn(name=”types”,discriminatorType=DiscriminatorType.INTEGER,length=1)//指定区分字段为types,类型为Integer长度为1
@DiscriminatorValue(value=”1”)//对应具体实体的值
public class Test implements Serializable{
…..
}
子类Child
@Transient
******* String tempStr;
@Lob //lob类型的字段
@Basic(fetch=FetchType.Lazy) //采用延迟加载,FetchType.EAGER不采用
@Column(name=”postattach”,columnDefinition=”LONGTEXT NOT NULL”)对应字段类型
******* String postAttach;
}
可以看到通过字段types来区分父子类数据,也是相当方便的。至于JPA提供的关联关系比如说一对多,多对一,多对多,也有相应的注解进行关联,有兴趣的朋友可以参考相关帮助文档。
以上讲述的都是JPA中以注解形式进行持久化,下面我们来看下采用XML元数据的形式,XML元数据信息以orm.xml命名,放置在类路径的META-INF 目录下。如果你提供了 XML 元数据描述信息,它将覆盖实体类中的注解元数据信息
<?xmlversion=”1.0”encoding=”UTF-8”?>
<entity-mappingsxmlns=”http://java.sun.com/xml/ns/persistence/orm”
xmlns=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”
http://java.sun.com/xml/ns/persistence/ormhttp://java.sun.com/xml/ns/persistence/orm_1_0.xsd”version=”1.0”>
<package>com.test</package>
<entityclass=”Test”>
<tablename=”test”/>
<attributes>
<idname=”id”>
<columnname=”id”/>
<generated-valuestrategy=”TABLE”/>
</id>
<basicname=”uname”>
<columnname=”uname”length=”30”/>
</basicname>
<basicname=”logintime”>
<columnname=”logintime”/>
<temporal>DATE</temporal>
</basicname>
</attributes>
</entity>
<entity-mappings>
以看到JPA元数据采用XML形式也是相当简单易懂的。
JPA重要API
JPA接口位于javax.persistence和javax.persistence.spi两个包中,javax.persistence包中大部分API都是注解类、EntityManager、Query等持久化操作接口。而javax.persistence.spi包中的4个API,是JPA的服务层接口
EntityManager
实体对象由实体管理器进行管理,通过EntityManager和持久化上下文进行交互
实体管理器有两种:
容器类:容器型的实体管理器由容器负责试题管理器之间的协作,Java EE应用服务器提供的就是管理型的实体管理器。
应用程序型:实体管理器的生命周期由应用程序控制,应用程序通过javax.persistence.EntityManagerFactoty的creaeEntityManager创建EntityManager实例
EntityManager的API
void persist(Object entity)
通过persist方法,新实体实例将转换为受控状态,就是说,当persist()方法所在的事务提交时,实体的数据保存到数据库中。
如果实体已经被持久化,那么调用persist()方法不会发生任何事情。
如果对一个已经删除的实体调用persist()方法,删除态的实体又转变为受控态
如果对游离状态的实体执行persist()操作,抛出IllegalArgumentException
一个实体调用persist()方法后,所有与之关联的实体,都将执行持久化操作
void remove(Object entity)
删除一个受控态的实体。
如果实体声明为级联删除(cascade=REMOVE或者cascade=ALL),被关联的实体也会被删除
在一个新建态或删除态的实体上调用remove()方法,将被忽略
在游离态的实体上调用remove()方法,将抛出IllegalArgumentException,相关事务将回滚
void flush()
将受控态的实体数据同步到数据库中
T merge(T entity)
将一个游离态的实体持久化到数据库中,并转换为受控态的实体
T find(Class entityClass.Object primaryKey)
以主键查询实体对象,entityClass是实体的类,primaryKey是主键值
Eg:Topic t = em.find(Topic.class,1);
Hibernate与Jpa的关系(2)的更多相关文章
- Hibernate与Jpa的关系
JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. JPA的总体思想和现有Hibernate.T ...
- [转]Hibernate与Jpa的关系,终于弄懂
原文地址:http://blog.sina.com.cn/s/blog_5f1619e80100yoxz.html 我知道Jpa是一种规范,而Hibernate是它的一种实现.除了Hibernate, ...
- Hibernate与Jpa的关系,终于弄懂
我知道Jpa是一种规范,而Hibernate是它的一种实现.除了Hibernate,还有EclipseLink(曾经的toplink),OpenJPA等可供选择,所以使用Jpa的一个好处是,可以更换实 ...
- Hibernate与Jpa的关系(1)
[转自:http://freewind.me/blog/20111129/588.html ] 我知道Jpa是一种规范,而Hibernate是它的一种实现.除了Hibernate,还有EclipseL ...
- (转载)Hibernate与Jpa的关系
我知道Jpa是一种规范,而Hibernate是它的一种实现.除了Hibernate,还有EclipseLink(曾经的toplink),OpenJPA等可供选择,所以使用Jpa的一个好处是,可以更换实 ...
- Hibernate和Jpa的关系
http://blog.sina.com.cn/s/blog_5f1619e80100yoxz.html Jpa是规范,Hibernate是实现,使用Hibernate的时候一定会使用到Jpa
- 转:spring data jpa、 hibernate、 jpa 三者之间的关系
原文链接:spring data jpa. hibernate. jpa 三者之间的关系 spring data jpa hibernate jpa 三者之间的关系 JPA规范与ORM框架之间的关系是 ...
- JPA和Hibernate到底是什么关系???
转自:https://www.cnblogs.com/mosoner/p/9494250.html 在学习框架的过程中,发现学的东西很多,但是感觉他们之间的联系区别都不是很了解,知道JPA可以去实现持 ...
- spring data jpa、 hibernate、 jpa 三者之间的关系
http://www.cnblogs.com/xiaoheike/p/5150553.html JPA规范与ORM框架之间的关系是怎样的呢? JPA规范本质上就是一种ORM规范,注意不是ORM框架-- ...
随机推荐
- 解决Mybatis连接Sql server 出现 Cannot load JDBC driver class 'com.mysql.jdbc.Driver '的问题
tomcat启动的时候没有错误,但是进行数据库操作就会有错误. 在网上找了很久 好不容易找到解决方法 转自 http://blog.csdn.net/ro_bot/article/details/5 ...
- phpcms 笔记
首先是要把首页分为三个部分 : 导航部分 .尾部和首页中间部分 用了三个不同的文件 header.html ; index.html; footer.html 在使用phpcms之前 首先 ...
- 实现全局同一编码:Filter
request.setCharacterEncoding("UTF-8");只对POST方式提交有用 对于GET方式 ,可以有装饰模式和适配器模式,对获取参数的函数进行重写. 对所 ...
- 使用点击二分图计算query-document的相关性
之前的博客中已经介绍了Ranking Relevance的一些基本情况(Click Behavior,和Text Match):http://www.cnblogs.com/bentuwuying/p ...
- Devexpress 中对RedailMenu的使用
最近项目中用到RadialMenu,效果图如下所示: 闲下来就对,devexpress中的RedialMenu的使用总结一下. 第一:假设RedialMenu中全部是BarButtonItem的情况. ...
- linux下安装node
经过一番的折腾终于在linux上安装了node,记录下来以免忘记 1.下载node 去官网下载最新的linux版本下对应node.js,node-v6.10.2-linux-x64.tar.gz 2. ...
- Docker for Mac与IntelliJ Docker Integration插件的兼容性问题
笔者在自己的Mac上安装的是Docker for Mac,而不是Docker Toolbox. 这两者最主要的区别在于Docker for Mac用HyperKit作为虚拟化解决方案而不是Virtua ...
- Android SQLite与ListView的简单使用
2017-04-25 初写博客有很多地方都有不足,希望各位大神给点建议. 回归主题,这次简单的给大家介绍一下Android SQLite与ListView的简单使用sqlite在上节中有介绍,所以在这 ...
- xmlplus 组件设计系列之四 - 列表
列表组件是极其常用的一类组件,是许多视图组件系统的必须包含的.列表可以做的很简单,只显示简洁的内容.列表也可以做的很复杂,用于展示非常丰富的内容. 组成元素 列表离不开列表项以及包含列表项的容器.下面 ...
- 学习Java之前操作环境的安装及配置
1.根据自己的系统版本下载相应版本的JDK(Java开发运行时环境) 查看自己系统版本的方法:在桌面上右键计算机(win7,win10是此电脑,XP是我的电脑),点击属性,进入到计算机属性页面以后里面 ...