Java JPA

在这里我将介绍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----------

  • geronimo-jms_1.1_spec-1.1.1.jar
  • geronimo-jpa_2.0_spec-1.0.jar
  • geronimo-jta_1.1_spec-1.1.1.jar

 

 

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.");
    }
}
 

你可能感兴趣的:(java,框架,应用服务器,orm,jpa)