SayNothing
人才
不清楚
我的首页
文章
相册
圈子
留言
管理
 
    当前所在页面:首页>>文章>>学习与分享JPA
学习与分享JPA
    作者:CodeSmith 来源: 发表时间:2008-01-05

 
 

近年来ORM(Object-Relational Mapping;对象关系映射,即实体对象和数据库表的映射)技术市场人声音鼎沸,异常热闹, Sun在充分吸收现有的优秀ORM框架设计思想的基础上,制定了新的JPA(Java Persistence API)规范。

那么什么是JPA呢?JPA是通过JDK5.0注解或XML描述对象-关系表的映射关系,并将运行期实体对象持久化到数据库中去。

这里我们要先谈一下什么叫实体(Entity),按照JPA规范,具有ORM元数据的领域对象就叫做实体。它应具备一下条件:

1.必须使用javax.persistence.Entity注解或XML映射文件中有对应的<entity>元素;

2.必须具有一个不带参数的构造函数,类不能声明为final,方法和需要持久化的属性也不能声明为final;

3.如果游离态的实体对象需要以值的方式进行传递(如通过Session bean的远程业务接口传递),则必须实现Serializable接口;

4.需要持久化的属性,起访问修饰符不能是public,它必须通过实体类方法进行访问。

 

下面我们来尝试对一个域对象进行JPA注解,使其成为一个实体类:

@Entity(name=”T_TEST”)
public class Test implements Serializable{
	@Id
	@GeneratedValue(strategy=GenerationType.TABLE)
	@Column(name=” id”)
	private int testId;

	@Column(name=”uname”,length=100)
	private String uname;

	@Column(name=”password”)
	private String password;

	@Column(name=”time”)
	@Temporal(TemporalType.Date)
	private Date loginTime;

	省略get/setter方法
}

下面对以上代码中所涉及的JPA注解进行一下说明

@Entity:将领域对象标注为一个实体类,表示该类需要持久化到数据库中,默认情况下类名即表名,通过name属性显式指定表名,如:name=”T_TEST”表示将Test保存到表T_TEST表中。

@Id:对应的属性是表的主键

@GeneratedValue:主键的产生策略,通过strategy属性进行指定,默认情况下,JPA自动选择一个最适合底层数据库的主键生成策略,如SqlServer对应的identitymysql对应的auto increment,java.persistence.GenerationType中定义了几种可以供选择的策略:

1.  Identity:表自动增长字段,Oracle不支持这种方式;

2.  AUTOJPA自动选择合适的策略,是默认选项;

3.  Sequence:通过序列产生主键,通过@SequenceGenerator注解指定序列名Mysql不支持这种方式。

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

 

@Colunm(name=”uname”):属性对应的表字段。我们并不需要指定表字段的类型,因为JPA 会根据反射从实体属性中获取类型;如果是字符串类型,我们可以指定字段长度,以便可以自动生成DDL语句。

 

@Temporal(TemporalType.DATE):如果属性是时间类型,因为数据表对时间类型有更严格的划分,所以必须指定具体时间类型,在java.persistence.TemporalType枚举中定义了三种时间类型:

Date:等于java.sql.Date;

Time:等于java.sql.Time;

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

@Entity

@DiscriminatorValue(value=”2”)

public class Child extends Test{

    

//如果我们不希望JPA将该属性持久化到数据库,则采用该注解

@Transient

private String tempStr

 

@Lob //lob类型的字段

@Basic(fetch=FetchType.Lazy) //采用延迟加载,FetchType.EAGER不采用

@Column(name=”postattach”,columnDefinition=”LONGTEXT NOT NULL”)对应字段类型

private String postAttach;

 

}

可以看到通过字段types来区分父子类数据,也是相当方便的。至于JPA提供的关联关系比如说一对多,多对一,多对多,也有相应的注解进行关联,有兴趣的朋友可以参考相关帮助文档。

 

以上讲述的都是JPA中以注解形式进行持久化,下面我们来看下采用XML元数据的形式,XML元数据信息以orm.xml命名,放置在类路径的META-INF 目录下。

 

<?xml version=”1.0” encoding=”UTF-8”?>
<entity-mappings 
xmlns=”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/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd” 
version=”1.0”>
<package>com.test</package>
<entity class=”Test”>
	<table name=”test”/>
	<attributes>
		<id name=”id”>
			<column name=”id”/>
			<generated-value strategy=”TABLE”/>
		</id>
		<basic name=”uname”>
			<column name=”uname” length=”30”/>
		</basic>
		<basic name=”logintime”>
			<column name=” logintime”/>
			<temporal>DATE</temporal>
		</basic>	
	</attributes>
</entity>
<entity-mappings>

可以看到JPA元数据采用XML形式也是相当简单易懂的。先写到这。继续学习中

 
 

(阅读 )   评论数(:6)
评论】 【收藏】
评论:共6条
谢谢你呀..我正需要了解JPA这方面的知道呀.
评论人: lengyu     评论时间: 2008-01-06 18:02:12
thanks
评论人: eddf     评论时间: 2008-01-08 17:24:56
评论人: 匿名用户     评论时间: 2008-01-16 18:43:36
评论人: 匿名用户     评论时间: 2008-01-16 18:43:43
ggggggggggggggggggg
评论人: 匿名用户     评论时间: 2008-02-11 17:45:18
eeeeeeeeeeeeeeeee
评论人: 匿名用户     评论时间: 2008-02-11 17:45:38

发表评论:
发表人:
评论: 
    
 
关于我们 | 诚聘英才 | 联系我们 | 广告业务 | 网站地图 | 法律声明

EasyJF开源团队版权所有  建议使用1024*768分辨率