在这里我将介绍java的JPA技术,这是我经过很长时间的尝试和经验总结而成,希望转载的人请留下我的链接
废话就少说了,现在就开始。
1.JPA(Java Persistence API)作为Java EE 5.0平台标准的ORM规范
目前很有名的JPA, ORM框架有:Hibernate,OpenJPA等。
其实ORM框架都将JPA作为底层来封装的,如果你看他们的源代码,基本都是这样了
他们的内容基本分为3部分:
1.1 ORM映射元数据,JPA支持XML和JDK 5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
1.2 JPA 的API,用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
1.3 查询语言,这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
2.实体对象
实体对象必须具备如下条件:
2.1 必须使用javax.persistence.Entity注解或者在XML映射文件中有对应的元素;
2.2 必须具有一个不带参的构造函数,类不能声明为final,方法和需要持久化的属性也不能声明为final;
2.3 必须实现Serializable接口;
2.4 需要持久化的属性,其访问修饰符不能是public,它们必须通过实体类方法进行访问。
其实以上的东东有点像POJO,但还是有所不同的,应用的时候其实满足POJO基本都行的,记住最后一条很重要。
3.使用注解元数据(METADATA)
package com; import java.util.Date; import javax.persistence.Basic; import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Message{ @Id private long id = System.currentTimeMillis(); @Basic private String message; @Basic private Date created = new Date(); public Message() { } public Message(String msg) { message = msg; } public void setId(long val) { id = val; } public long getId() { return id; } public void setMessage(String msg) { message = msg; } public String getMessage() { return message; } public void setCreated(Date date) { created = date; } public Date getCreated() { return created; } }
@Entity:将领域对象标注为一个实体,表示需要保存到数据库中,默认情况下类名即为表名,通过name属性显式指定表名
@Id :对应的属性是表的主键
@GeneratedValue:主键的产生策略,通过strategy属性指定。默认情况下,JPA自动选择一个最适合底层数据库的主键生成策略
1) IDENTITY:表自增键字段,Oracle不支持这种方式;
2) AUTO: JPA自动选择合适的策略,是默认选项;
3) SEQUENCE:通过序列产生主键,通过@SequenceGenerator注解指定序列名,MySql不支持这种方式;
4) TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。不同的JPA实现商生成的表名是不同的
@Column(name = "?"):属性对应的表字段。我们并不需要指定表字段的类型,因为JPA会根据反射从实体属性中获取类型;如果是字符串类型,我们可以指定字段长度,以便可以自动生成DDL语句
@Temporal(TemporalType.DATE):如果属性是时间类型,因为数据表对时间类型有更严格的划分,所以必须指定具体时间类型
1) DATE :等于java.sql.Date
2) TIME :等于java.sql.Time
3) TIMESTAMP :等于java.sql.Timestamp
4.继承关系
SINGLE_TABLE:父子类都保存到同一个表中,通过字段值进行区分, 区别的字段通过 @DiscriminatorColumn说明,区分字段对应该实体的值通过@DiscriminatorValue指定
JOINED:父子类相同的部分保存在同一个表中,不同的部分分开存放,通过表连接获取完整数据;
TABLE_PER_CLASS:每一个类对应自己的表,一般不推荐采用这种方式。
如果我们不希望将某个属性持久化到数据表中,则可以通过@Transient注解显式指定
比如:
@Transient
private boolean tempProp1;
@oneToMany
@ManyToOne
@OneToOne
@ManyToMany
都是用集合映射了,相应的和class进行对应就好
他们还分为单向的和双向的两种
5.使用XML对应数据
如果你提供了XML元数据描述信息,它将覆盖实体类中的注解元数据信息。XML元数据信息以 orm.xml命名,放置在类路径的META-INF目录下。
6.介绍JPA的核心类
EntityManager的类型
实体对象由实体管理器进行管理,JPA使用javax.persistence.EntityManager代表实体管理器。实体管理器和持久化上下文关联,持久化上下文是一系列实体的管理环境,我们通过EntityManager和持久化上下文进行交互。
容器型:容器型的实体管理器由容器负责实体管理器之间的协作,在一个JTA事务中,一个实体管理器的持久化上下文的状态会自动广播到所有使用EntityManager的应用程序组件中。Java EE应用服务器提供的就是管理型的实体管理器; 应用程序型:实体管理器的生命周期由应用程序控制,应用程序通过javax.persistence.EntityManagerFactory的createEntityManager创建EntityManager实例。
7. EntityManager的创建过程
javax.persistence.spi.PersistenceProvider接口由JPA的实现者提供,该接口由启动者调用,以便创建一个EntityManagerFactory实例。它定义了创建一个EntityManagerFactory实例的方法:
EntityManagerFactorycreateContainerEntityManagerFactory(PersistenceUnitInfo info, Map map)
javax.persistence.spi.PersistenceUnitInfo入参提供了创建实体管理器所需要的所有信息,这些信息根据JPA的规范,必须放置在META-INF/persistence.xml文件中。
PersistenceUnitInfo接口拥有了一个void addTransformer(ClassTransformer transformer)方法,通过该方式可以添加一个javax.persistence.spi.ClassTransformer,并通过 PersistenceProvider开放给容器,以便容器在实体类文件加载到JVM之前进行代码的增强,使元数据生效。JPA厂商负责提供 ClassTransformer接口的实现。
8.实体的状态
实体的状态
实体对象拥有以下4个状态,这些状态通过调用EntityManager接口方法发生迁移:
新建态:新创建的实体对象,尚未拥有持久化主键,没有和一个持久化上下文关联起来。
受控态:已经拥有持久化主键并和持久化上下文建立了联系;
游离态:拥有持久化主键,但尚未和持久化上下文建立联系;
删除态:拥有持久化主键,已经和持久化上下文建立联系,但已经被安排从数据库中删除。
9.Query
JPA使用javax.persistence.Query接口代表一个查询实例,Query实例由EntityManager通过指定查询语句构建。该接口拥有众多执行数据查询的接口方法:
◆Object getSingleResult():执行SELECT查询语句,并返回一个结果;
◆List getResultList() :执行SELECT查询语句,并返回多个结果;
◆Query setParameter(int position, Object value):通过参数位置号绑定查询语句中的参数,如果查询语句使用了命令参数,则可以使用Query setParameter(String name, Object value)方法绑定命名参数; ◆Query setMaxResults(int maxResult):设置返回的最大结果数;
◆int executeUpdate():如果查询语句是新增、删除或更改的语句,通过该方法执行更新操作;
10.JPA 的简单查询 JPQL
使用query的setParameter()来进行非注入查询,其他的都和别的ORM框架差不多,这里就不介绍了
以上就是一些理论,我想大家也需要一些事例,嘻嘻 马上就来。。。。。
javaVersion
----------------- 最好是JDK1.6
OpenJAP need JAR
我们用的是2.x以上的版本
openjpa-<version>.jar
commons-collections-3.2.1.jar
commons-lang-2.1.jar
commons-pool-1.5.3.jar
serp-1.13.1.jar
J2EE----------
OpenJPA session Manager
public class DaoSessionManager { private static EntityManagerFactory emf; private static final ThreadLocal<EntityManager> baseThread = new ThreadLocal<EntityManager>(); private static DebugLog debugLog = DebugLog.getInstance(DaoSessionManager.class); private static final DaoDataSource daoDataSource = new DaoDataSource(); public static EntityManager getCurrentSession() { return (EntityManager) baseThread.get(); } protected static synchronized EntityManagerFactory getSessionFactory(String name, Map<String, Object> props) { if (emf == null) { emf = Persistence.createEntityManagerFactory(name, props); } return emf; } public static void openSession() { EntityManager em = (EntityManager) baseThread.get(); if (em == null) { try { String persistenceUnit = daoDataSource.getPersistenceUnit(); Map<String, Object> properties = daoDataSource.getProperties(); em = getSessionFactory(persistenceUnit, properties).createEntityManager(); } catch (Exception e) { debugLog.debug("failed to load connection information from data source."); } baseThread.set(em); debugLog.debug("Jpa session opened."); } } public static void closeSession() { EntityManager em = (EntityManager) baseThread.get(); baseThread.set(null); if (em != null && em.isOpen()) { em.close(); } debugLog.debug("Jpa session closed."); } }