前言
本文仅代表作者的个人观点;
本文的内容仅限于技术探讨,不能作为指导生产环境的素材;
本文素材是红帽公司产品技术和手册;
本文分为系列文章,将会有多篇,初步预计将会有9篇。
本篇文章借助了互联网的材料,参考链接如下。
参考文档:
http://www.blogjava.net/jesson2005/articles/380880.html
https://www.jianshu.com/p/091360c47e6b
https://blog.csdn.net/u014421556/article/details/52635000
一、先搞清J2SE和Java EE的区别
— Java EE环境,包括EJB容器和Web容器。 (1)Web容器:只运行Web应用的容器,例如Tomcat就是开源的Web容器,它可以运行JSP、Servlet等。 -----------这也就是我们常说的web server。 (2)EJB容器:运行在EJB组件的容器,提供EJB组件的状态管理、事务管理、线程管理、远程数据资源访问、连接管理和安全性管理等系统级服务。例如JBoss为EJB容器和Web容器(Web容器是集成了Tomcat)结合。 ---------------这也就是我们常说的app server,即传统意义上的中间件。 部署在EJB容器中的JAR包都可以认为是运行在EJB容器中。但JBoss中的Web应用,比如war包中的类就不是运行在EJB容器中,而是运行在Web容器中。 (war主要是web类、jar主要是app类) 二 J2SE环境 最普通Java运行环境,例如一个HelloWorld的Java程序就是运行在J2SE的环境中,通常使用main入口方法作为程序启动的触发。 也就是通过java -jar可以运行。
二、应用对数据的访问
Java应用需要访问数据源,企业级常见比较多的是关系型数据库。应用要获取数据库表中的数据,每次都直接通过JDBC链接、用SQL去查询显然不现实。
我们开发一个应用程序的时候,肯定会写不少数据访问层的代码,用来从数据库保存、删除、读取对象信息
这就需要Object Relational Mapping,简称ORM的技术。
ORM解决的主要问题是对象关系的映射。我们可以在Java中创建一个持久化类,让这个类和一个数据库表对应,类的每个实例对应表中的一条记录,类的每个属性对应表的每个字段。
Entity | Table |
---|---|
类的名称 | Table name |
类的属性 | 数据库表中的列 |
类的实例 | 数据库表中的行 |
例如,数据库中有的表,叫importperson,内容如下:
那么,通过ORM技术,我们需要创建一个类,类的名称叫importperson(默认和数据库表名称相同),这个实体类被映射到数据库表:
@Entity
public class importperson {
...
}
看起来ORM不错哦?
ORM技术特点: 1.提高了开发效率。由于ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。
2.ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。
那么,实现ORM,是否一个实体类就够了呢?显然不是,因为还需要设定对数据库的链接方式、定义对数据库操作的接口。
我们需要JPA---Java Persistence API。
三、JPA的本质
JPA规范本质上就是一种ORM规范,不是ORM框架——因为JPA并未提供ORM实现,它只是制订了一些规范,提供了一些编程的API接口,但具体实现则由服务厂商来提供实现,JBoss应用服务器底层就以Hibernate作为JPA的实现。
既然JPA作为一种规范——也就说JPA规范中提供的只是一些接口,显然接口不能直接拿来使用。虽然应用程序可以面向接口编程,但JPA底层一定需要某种JPA实现,否则JPA依然无法使用。
Sun之所以提出JPA规范,其目的是以官方的身份来统一各种ORM框架的规范,包括著名的Hibernate、TopLink等。开发者面向JPA规范的接口,但底层的JPA实现可以任意切换:觉得Hibernate好的,可以选择Hibernate JPA实现;觉得TopLink好的,可以选择TopLink JPA实现。
下图是JPA和Hibernate、TopLink等ORM框架之间的关系:
JPA的API有主要以下几个:实体(entity)、持久性单元(persistence units)、持久性上下文( persistence context)、Entity Manager。我们先看Entity Manager。
四、JPA中的entity
entity class映射到关系数据库中的表。 entity class的每个实例都有一个主键字段。 主键字段用于将实体实例映射到数据库表中的行。在Java中,entity是一个简单的旧Java对象(POJO)类,它使用@Entity注释进行了注释。 entity类中的所有字段默认存储在数据库中,并称为持久字段。 声明为临时的属性不存储在数据库表中,并且被称为非持久性。
关于entity,我们在前文也提及到。
@Entity
@Table(name="ThingsToDo")
public class TodoItem {
...}
五、JPA中的persistence units
1. 持久性单元(persistence units)。
持久性单元是存储在应用程序存档中的所有实体类和persistence.xml文件的集合。 persistence.xml是一个配置文件,其中包含有关实体类,数据源,事务类型和其他配置信息的信息。
我们来看一个 persistence.xml,它通过Hibernate调用JDBC创建对数据库的连接。
六、JPA中的.Entity Manager
JPA中用于增删改查的接口,它的作用相当于一座桥梁,连接内存中的java对象和数据库的表。Entity Manager获取对entity的引用,并对数据库执行实际的CRUD(创建,读取,更新和删除)操作。
Entity Manager有两种托管方式:
容器托管的EntityManager对象最简单,程序员不需要考虑EntityManager连接的释放,以及事务等复杂的问题,所有这些都交 给容器去管理。容器托管的EntityManager对象必须在EJB容器中运行,而不能在Web容器和J2SE的环境中运行.(EJB容器其实就是指的中间件,如JBoss EAP。也就是说这种方式的EntityManager,必须以jar包形式运行在中间件上)。
应用托管的EntityManager对象,程序员需要手动地控制它的释放和连接、手动地控制事务等。但这种获得应用托管的 EntityManager对象的方式,不仅可以在EJB容器中应用,也可以使 JPA脱离EJB容器,而与任何的Java环境集成,比如说Web容器、J2SE环境等。所以从某种角度上来说,这种方式是JPA能够独立于EJB环境运 行的基础。
七、JPA中的持久性上下文( persistence context)
被EntityManager持久化到数据库中的对象(也就是把java应用生成、修改的数据保存到数据库表),或者从数据库拉入内存中的对象(把数据库表的数据读到java中),也会同时被一个持久化上下文(PersistenceContext)管理。所以说:持久化上下文 persistence context,是负责将Entity的状态与数据库状态进行同步的代码。
当一个实体与持久化上下文分离时(例如通过调用EntityManager上的detach方法)该实体的状态不再与数据库保持同步。
EntityManager和PersistenceContext之间的关系,一般可以是多对一的,即多个EntityManager可以同时指向一个PersistenceContext。这其实很好理解,就是EntityManager虽然有多个实例,但是它们背后的持久化上下文却只有一个。
八、几者之间的关系
一个entity其实就是一个class,只是定了与数据库表的对应。如上图,class叫大魏,数据库中也有一张表叫大魏(类的名称可以和数据库表名不同,使用@Table指定即可)。
大魏这个类,在被生成对象时,会从数据库表中读数据,然后可能会对数据修改,修改的这些数据,会存到持久性上下文中(运行在内存中),在默写情况下,会被存回数据库表中(例如提交)。
java对数据库表的操作,实际上是使用entity manager调用CRUD完成的。而entity manager之所以能对数据库做操作,是因为其底层调用Hibernate,封装了JDBC。而Hibernate相关定义的静态配置,是存放到persistence units中的。
(默认模式下)entity manager是运行到EJB container中,也就是中间件中的。
魏新宇