在Java SE环境下使用JPA1.0(Java EE 5.0 中的主要组成部分,TopLink配置

Java Persistence API 1.0( EJB3 Entity Bean) 在Java EE5中, Entity Bean做为EJB规范中负责持久化的组件将逐渐成为一个历史名词了,作为J2EE 4规范中最为人所垢病的Entity Bean在Java EE5中被推到重来,取而代之的是java开发的通用持久化规范Java Persistence API 1.0。JPA作为java中负责关系数据持久化的组件已经完全独立出来成为一个单独的规范,而不再属于Enterprise Java Bean的范畴。

Java Persistence AP(JPA)可以说是java持久化技术的一个集大成者,它吸取了Hiberante,JDO,TopLink等优秀技术和框架,将这几年发展成熟起来的基于POJO模型的O/R Mapping技术标准化,成为在J2EE和J2SE环境中通用的java持久化API。值得注意的是Java Persistence API并不是J2EE环境专用,而是在java中的通用API。意味着我们可以在任何需要访问关系数据库的地方使用JPA,甚至包括swing开发的桌面应用。JPA也不要求一定在J2EE容器中才能运行,而是任何有JVM的环境都可以运用。这就使得我们可以很容易的把JPA作为一个持久化组件自由地和各种容器/框架(EJB3容器, Spring等等)组合。

下面是我做的一个JPA 在 Java SE 环境下的使用范例.

一、搭建环境

1) 搭建数据库环境

1、安装数据库(MySQL 5.0.24), 用户: root,密码: (空) 。
2、建库piscesdb。
3、建表address:
droptableaddress;

createtableaddress(
addressID
intnotnull,
city
varchar(55)notnull,
street
varchar(55)NOTNULL,
zip
varchar(8)NOTNULL,
PRIMARYKEY(addressID)
);

insertintoaddressvalues(1,"深圳","坂田市场","518001");
insertintoaddressvalues(2,"深圳","坂田路口","518002");
insertintoaddressvalues(3,"深圳","四季花城","518003");

4、建表userinfo:
drop table userinfo;

create table userinfo(
userID
int not null , /* *用户id */
username
varchar ( 20 ) not null , /* *姓名 */
birthday
datetime null , /* *出生日期 */
sex
varchar ( 8 ) not null , /* *性别 */
addressID
int not null , /* *地址id */
PRIMARY KEY (userID)
);

insert into userinfo values ( 1 ,"张先生", null ,"male", 1 );
insert into userinfo values ( 2 ,"李某某", null ,"male", 2 );
insert into userinfo values ( 3 ,"王某某", ' 2006-08-10 ' ,"female", 3 );
insert into userinfo values ( 4 ,"陈某某", ' 2006-08-12 ' ,"male", 3 );



2) 获取额外的jar包

下载JPA的实现类, 去https://glassfish.dev.java.net/downloads/persistence/JavaPersistence.html下载GlassFish v1 FCS branch版本,
进行安装后得到toplink-essentials.jar,toplink-essentials-agent.jar 两个包,将这两个包和mysql的驱动包加入到项目的classpath路径中去。
编译
toplink源码需要 javax.transaction、org.apache.tools.ant 两个包
项目工程路径不要含中文, 因为 toplink 暂时不支持。

3) 开发环境

JDK: jdk 6.0 beta2 (JDK 5.0 也可以)
IDE: NetBeans 5.0 中文版

二、开发

1) 创建实体Entity类

1、地址类 Address :
/*
*Address.java
*/

package org.pisces.persist;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

/**
*
*
@author kamhung
*/
@Entity
public class Address implements Serializable{
// 地址id,不能为空,必须唯一
@Id
@Column(name
= " addressid " ,unique = true ,nullable = false )
private int addressid;

// 城市,不能为空
@Column(name = " city " ,nullable = false )
private Stringcity;

// 街道,不能为空
@Column(name = " street " ,nullable = false )
private Stringstreet;

// 邮政编码,不能为空
@Column(name = " zip " ,nullable = false )
private Stringzip;

public Address(){
}

public Address( int addressid){
this .setAddressid(addressid);
}

public int getAddressid(){
return this .addressid;
}

public void setAddressid( int addressid){
this .addressid = addressid;
}

public StringgetCity(){
return this .city;
}

public void setCity(Stringcity){
this .city = city;
}

public StringgetStreet(){
return street;
}

public void setStreet(Stringstreet){
this .street = street;
}

public StringgetZip(){
return this .zip;
}

public void setZip(Stringzip){
this .zip = zip;
}

@Override
public int hashCode(){
return this .addressid;
}

@Override
public boolean equals(Objectobject){
if ( ! (object instanceof Address)) return false ;
final Addressother = (Address)object;
return this .addressid == other.addressid;
}

@Override
public StringtoString(){
return " Address[addressid= " + getAddressid() + " ,city=' " + getCity() + " ',street=' " + getStreet() + " ',zip=' " + getZip() + " '] " ;
}
}

2、用户类 UserInfo:
/*
*UserInfo2.java
*/

package org.pisces.persist;

import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import static javax.persistence.CascadeType. * ;

/**
*
*
@author kamhung
*/
@Entity
public class UserInfo implements Serializable{
// 用户id,不能为空,必须唯一
@Id
@Column(name
= " userid " ,unique = true ,nullable = false )
private int userid;

// 用户名,不能为空
@Column(name = " userName " ,nullable = false )
private StringuserName;

// 性别,不能为空
@Column(name = " sex " ,nullable = false )
private Stringsex;

// 出生日期,可以为空
@Column(name = " birthday " )
private Timestampbirthday;

// 地址,不能为空
// PERSIST表示更新、新增UserInfo数据时会同时更新、新增Address的数据
// REMOVE表示从数据库删除UserInfo会同时删除Address表中对应的数据
@OneToOne(cascade = {PERSIST,REMOVE})
@JoinColumn(name
= " addressID " ,nullable = false )
private Addressaddress;

public UserInfo(){
}

public UserInfo( int userid){
this .setUserid(userid);
}

@Override
public int hashCode(){
return this .getUserid();
}

@Override
public boolean equals(Objectobject){
if ( ! (object instanceof UserInfo)) return false ;
final UserInfoother = (UserInfo)object;
return this .userid == other.userid;
}

@Override
public StringtoString(){
return " UserInfo[userid= " + this .userid + " ,userName=' " + userName + " ',sex=' " + sex
+ " ',birthday= " + birthday + " ,address= " + address + " ] " ;
}

public int getUserid(){
return userid;
}

public void setUserid( int userid){
this .userid = userid;
}

public StringgetUserName(){
return userName;
}

public void setUserName(StringuserName){
this .userName = userName;
}

public TimestampgetBirthday(){
return birthday;
}

public void setBirthday(Timestampbirthday){
this .birthday = birthday;
}

public StringgetSex(){
return sex;
}

public void setSex(Stringsex){
this .sex = sex;
}

public AddressgetAddress(){
return address;
}

public void setAddress(Addressaddress){
this .address = address;
}
}


2) 创建配置文件persistence.xml

在项目src文件夹下创建一个META-INF文件夹(有就不用创建了), META-INF文件夹下建一个persistence.xml文件, 内容为:

<? xmlversion="1.0"encoding="UTF-8" ?>
< persistence version ="1.0" xmlns ="http://java.sun.com/xml/ns/persistence"
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
="http://java.sun.com/xml/ns/persistencehttp://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" >
<!-- transaction-type可选值有:JTA、RESOURCE_LOCAL;
在JavaEE环境下默认值为JTA,在JavaSE环境下默认值为RESOURCE_LOCAL;
如果值为JTA的话,则必须要指定<jta-data-source>的值
-->
< persistence-unit name ="piscesPU" transaction-type ="RESOURCE_LOCAL" >
< description > 这是piscesPU持久化单元的一个简单描述 </ description >
<!-- 指明javax.persistence.spi.PersistenceProvider的实现类,一般来说该节点可以省略 -->
< provider > oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider </ provider >
<!-- 在JavaSE环境下必须定义所有的实体Entity类,也可以用<mapping-file>或<jar-file>节点代替 -->
< class > org.pisces.persist.UserInfo </ class >
< class > org.pisces.persist.Address </ class >
<!--
//可以定义jndi资源代替properties节点中的数据库配置,
//但是在调用Persistence.createEntityManagerFactory方法前必须保证此资源已经注入程序中.
<jta-data-source>jdbc/persist</jta-data-source>
-->

<!-- properties节点是用来定义各种JPA实现包所定义的属性配置 -->
<!-- 下面列举的是toplink实现包中可以配置的部分属性 -->
< properties >
<!-- 数据库连接配置,JDBC驱动 -->
< property name ="toplink.jdbc.driver" value ="com.mysql.jdbc.Driver" />
<!-- 数据库连接配置,URL -->
< property name ="toplink.jdbc.url" value ="jdbc:mysql://localhost:3306/piscesdb" />
<!-- 数据库连接配置,用户名 -->
< property name ="toplink.jdbc.user" value ="root" />
<!-- 数据库连接配置,密码 -->
< property name ="toplink.jdbc.password" value ="" />

<!-- 数据库连接池配置,可写的连接池的最大连接数,默认为10 -->
< property name ="toplink.jdbc.write-connections.max" value ="10" />
<!-- 数据库连接池配置,可写的连接池的最大连接数,默认为5 -->
< property name ="toplink.jdbc.write-connections.min" value ="5" />
<!-- 数据库连接池配置,只读的连接池的最大连接数,默认为2 -->
< property name ="toplink.jdbc.read-connections.max" value ="2" />
<!-- 数据库连接池配置,只读的连接池的最大连接数,默认为2 -->
< property name ="toplink.jdbc.read-connections.min" value ="2" />
<!-- 数据库连接池配置,只读的连接池是否可以共享,默认为false -->
< property name ="toplink.jdbc.read-connections.shared" value ="false" />
<!-- 是否绑定所有jdbc属性,默认为true -->
< property name ="toplink.jdbc.bind-parameters" value ="true" />

<!-- 缓冲配置,以下三个属性值为默认设置;
可以 default改为entity名(@Entity注释中的name属性值)或者类名来指定该entity的缓冲配置,如:
<propertyname="toplink.cache.size.org.pisces.persist.UserInfo"value="2"/>
<propertyname="toplink.cache.type.org.pisces.persist.UserInfo"value="SoftWeak"/>
<propertyname="toplink.cache.shared.org.pisces.persist.UserInfo"value="true"/>
-->
< property name ="toplink.cache.size.org.pisces.persist.UserInfo" value ="2" />
<!-- 缓冲配置,缓冲大小,默认为1000 -->
< property name ="toplink.cache.size.default" value ="1000" />
<!-- 缓冲配置,缓冲类型,可选值为{Weak、SoftWeak、HardWeak、Full、NONE},不区分大小,默认为SoftWeak -->
< property name ="toplink.cache.type.default" value ="SoftWeak" />
<!-- 缓冲配置,是否共享缓冲,默认为false -->
< property name ="toplink.cache.shared.default" value ="false" />

<!-- 日志配置,日志级别,默认值为java.util.logging.Level在系统中的值 -->
< property name ="toplink.logging.level" value ="SEVERE" />
<!-- 日志配置,日志是否记录当前时间,默认为true -->
< property name ="toplink.logging.timestamp" value ="true" />
<!-- 日志配置,日志是否记录当前线程名,默认为true -->
< property name ="toplink.logging.thread" value ="true" />
<!-- 日志配置,日志是否记录当前会话名,默认为true -->
< property name ="toplink.logging.session" value ="true" />
<!-- 日志配置,日志是否记录异常堆栈,默认为true -->
< property name ="toplink.logging.exceptions" value ="true" />

<!-- 目标数据库类型,截至目前为止可选值为{Auto、Oracle、Attunity、Cloudscape、Database、DB2、DB2Mainframe
、 DBase、Derby、HSQL、Informix、JavaDB、MySQL4、PostgreSQL、SQLAnyWhere、 SQLServer、Sybase、TimesTen},
不区分大小,默认为Auto,即 TopLink自动匹配对应的数据库类型
-->
< property name ="toplink.target-database" value ="Auto" />

<!-- 指定会话名称,默认为系统自动产生唯一性名称 -->
< property name ="toplink.session-name" value ="pisces_session_name" />

<!-- 设置是否为weaving,默认为true -->
< property name ="toplink.weaving" value ="true" />

<!-- 指定目标应用服务器类型,截至目前为止可选值为{None、OC4J_10_1_3、SunAS9}(以后可能会扩展其他值的),
在 JavaSE环境下值为None,不区分大小,默认为None
-->
< property name ="toplink.target-server" value ="None" />

<!-- 指定实现oracle.toplink.essentials.tools.sessionconfiguration.DescriptorCustomizer的类名,
toplink.descriptor.customizer. 为前缀,后面跟entity名(@Entity注释中的name属性值)或者entity类名,
该类中的customize方法在执行 了所有的属性(除了toplink.session.customizer之外)后运行,如:
<propertyname="toplink.descriptor.customizer.org.pisces.persist.UserInfo"value="org.pisces.persist.SimpleDescriptorCustomizer"/>
<propertyname="toplink.descriptor.customizer.org.pisces.persist.Address"value="org.pisces.persist.SimpleDescriptorCustomizer"/>
-->
<!-- 指定实现oracle.toplink.essentials.tools.sessionconfiguration.SessionCustomizer的类名,
该类中的customize方法在执行了所有的属性后运行,如:
<propertyname="toplink.session.customizer"value="org.pisces.persist.SimpleSessionCustomizer"/>
-->
</ properties >
</ persistence-unit >
</ persistence >



3) 创建Entity的管理类

管理类SimpleManager是用来对实体Entity进行操作管理的.
/*
*SimpleManager.java
*/

package org.pisces.persist;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

/**
*
*
@author kamhung
*/
public class SimpleManager{

//一个持久单元对应一个EntityManagerFactory
privatestaticfinalEntityManagerFactoryemf=Persistence.createEntityManagerFactory("piscesPU");

privateSimpleManager(){
//donothing
}

/**
*删除用户id=6的数据
*/
publicstaticvoiddelete(){
finalEntityManagerem=emf.createEntityManager();
//找不到数据的话这里会抛异常
UserInfoinfo=em.find(UserInfo.class,6);
try{
em.getTransaction().begin();
em.remove(info);
em.getTransaction().commit();
}
finally{
em.close();
}
}

/**
*修改用户id=6的数据
*/
publicstaticvoidupdate(){
finalEntityManagerem=emf.createEntityManager();
//找不到数据的话这里会抛异常
UserInfoinfo=em.find(UserInfo.class,6);
info.setUserName(
"哈哈");
info.getAddress().setStreet(
"坂田2");
try{
em.getTransaction().begin();
//自动将info更新到数据库
em.getTransaction().commit();
}
finally{
em.close();
}
}

/**
*查询所有用户数据
*/
publicstaticvoidquery(){
longs=System.currentTimeMillis();
//数据库连接失败这里会抛出异常
finalEntityManagerem=emf.createEntityManager();
longe=System.currentTimeMillis();
System.out.println(
"连接数据库耗时:"+(e-s)+"毫秒");
//获取数据
@SuppressWarnings("unchecked")
List
<UserInfo>list=em.createQuery("SELECTaFROMUserInfoa").getResultList();
inti=0;
for(UserInfoinfo:list){
System.out.println(
""+(++i)+"个值为:"+info);
}
em.close();
}

/**
*创建用户id=6的一条数据,地址id=6
*/
publicstaticvoidcreate(){
finalEntityManagerem=emf.createEntityManager();

UserInfoinfo
=newUserInfo(6);
info.setSex(
"male");
info.setUserName(
"张某某");
info.setBirthday(
newjava.sql.Timestamp(System.currentTimeMillis()));
Addressnaddr
=newAddress(6);
naddr.setCity(
"深圳");
naddr.setStreet(
"坂田");
naddr.setZip(
"518000");
info.setAddress(naddr);

try{
em.getTransaction().begin();
em.persist(info);
em.getTransaction().commit();
}
finally{
em.close();
}
}
}


三、运行

1、 编写main函数:
/*
*Main.java
*/

package org.pisces;

import org.pisces.persist.SimpleManager;

/**
*
*
@author kamhung
*/
public class Main{

/**
*主函数
*/
public static void main(String[]args) throws Throwable{
SimpleManager.query();
SimpleManager.create();
System.out.println(
" 新增一条数据后进行查询 " );
SimpleManager.query();
SimpleManager.update();
System.out.println(
" 修改一条数据后进行查询 " );
SimpleManager.query();
SimpleManager.delete();
System.out.println(
" 删除一条数据后进行查询 " );
SimpleManager.query();
}
}

2、 运行结果如下:
run:
连接数据库耗时:1000毫秒
第1个值为:UserInfo[userid
= 1 ,userName = ' 先生 ' ,sex = ' male ' ,birthday = null ,address = Address[addressid = 1 ,city = ' 深圳 ' ,street = ' 坂田市场 ' ,zip = ' 518001 ' ]]
第2个值为:UserInfo[userid
= 2 ,userName = ' 李某某 ' ,sex = ' male ' ,birthday = null ,address = Address[addressid = 2 ,city = ' 深圳 ' ,street = ' 坂田路口 ' ,zip = ' 518002 ' ]]
第3个值为:UserInfo[userid
= 3 ,userName = ' 王某某 ' ,sex = ' female ' ,birthday = 2006 - 08 - 10 00 : 00 : 00.0 ,address = Address[addressid = 3 ,city = ' 深圳 ' ,street = ' 四季花城 ' ,zip = ' 518003 ' ]]
第4个值为:UserInfo[userid
= 4 ,userName = ' 陈某某 ' ,sex = ' male ' ,birthday = 2006 - 08 - 12 00 : 00 : 00.0 ,address = Address[addressid = 3 ,city = ' 深圳 ' ,street = ' 四季花城 ' ,zip = ' 518003 ' ]]

新增一条数据后进行查询
连接数据库耗时:0毫秒
第1个值为:UserInfo[userid
= 1 ,userName = ' 先生 ' ,sex = ' male ' ,birthday = null ,address = Address[addressid = 1 ,city = ' 深圳 ' ,street = ' 坂田市场 ' ,zip = ' 518001 ' ]]
第2个值为:UserInfo[userid
= 2 ,userName = ' 李某某 ' ,sex = ' male ' ,birthday = null ,address = Address[addressid = 2 ,city = ' 深圳 ' ,street = ' 坂田路口 ' ,zip = ' 518002 ' ]]
第3个值为:UserInfo[userid
= 3 ,userName = ' 王某某 ' ,sex = ' female ' ,birthday = 2006 - 08 - 10 00 : 00 : 00.0 ,address = Address[addressid = 3 ,city = ' 深圳 ' ,street = ' 四季花城 ' ,zip = ' 518003 ' ]]
第4个值为:UserInfo[userid
= 4 ,userName = ' 陈某某 ' ,sex = ' male ' ,birthday = 2006 - 08 - 12 00 : 00 : 00.0 ,address = Address[addressid = 3 ,city = ' 深圳 ' ,street = ' 四季花城 ' ,zip = ' 518003 ' ]]
第5个值为:UserInfo[userid
= 6 ,userName = ' 张某某 ' ,sex = ' male ' ,birthday = 2006 - 08 - 14 21 : 45 : 08.187 ,address = Address[addressid = 6 ,city = ' 深圳 ' ,street = ' 坂田 ' ,zip = ' 518000 ' ]]

修改一条数据后进行查询
连接数据库耗时:0毫秒
第1个值为:UserInfo[userid
= 1 ,userName = ' 先生 ' ,sex = ' male ' ,birthday = null ,address = Address[addressid = 1 ,city = ' 深圳 ' ,street = ' 坂田市场 ' ,zip = ' 518001 ' ]]
第2个值为:UserInfo[userid
= 2 ,userName = ' 李某某 ' ,sex = ' male ' ,birthday = null ,address = Address[addressid = 2 ,city = ' 深圳 ' ,street = ' 坂田路口 ' ,zip = ' 518002 ' ]]
第3个值为:UserInfo[userid
= 3 ,userName = ' 王某某 ' ,sex = ' female ' ,birthday = 2006 - 08 - 10 00 : 00 : 00.0 ,address = Address[addressid = 3 ,city = ' 深圳 ' ,street = ' 四季花城 ' ,zip = ' 518003 ' ]]
第4个值为:UserInfo[userid
= 4 ,userName = ' 陈某某 ' ,sex = ' male ' ,birthday = 2006 - 08 - 12 00 : 00 : 00.0 ,address = Address[addressid = 3 ,city = ' 深圳 ' ,street = ' 四季花城 ' ,zip = ' 518003 ' ]]
第5个值为:UserInfo[userid
= 6 ,userName = ' 哈哈 ' ,sex = ' male ' ,birthday = 2006 - 08 - 14 21 : 45 : 08.187 ,address = Address[addressid = 6 ,city = ' 深圳 ' ,street = ' 坂田2 ' ,zip = ' 518000 ' ]]

删除一条数据后进行查询
连接数据库耗时:0毫秒
第1个值为:UserInfo[userid
= 1 ,userName = ' 先生 ' ,sex = ' male ' ,birthday = null ,address = Address[addressid = 1 ,city = ' 深圳 ' ,street = ' 坂田市场 ' ,zip = ' 518001 ' ]]
第2个值为:UserInfo[userid
= 2 ,userName = ' 李某某 ' ,sex = ' male ' ,birthday = null ,address = Address[addressid = 2 ,city = ' 深圳 ' ,street = ' 坂田路口 ' ,zip = ' 518002 ' ]]
第3个值为:UserInfo[userid
= 3 ,userName = ' 王某某 ' ,sex = ' female ' ,birthday = 2006 - 08 - 10 00 : 00 : 00.0 ,address = Address[addressid = 3 ,city = ' 深圳 ' ,street = ' 四季花城 ' ,zip = ' 518003 ' ]]
第4个值为:UserInfo[userid
= 4 ,userName = ' 陈某某 ' ,sex = ' male ' ,birthday = 2006 - 08 - 12 00 : 00 : 00.0 ,address = Address[addressid = 3 ,city = ' 深圳 ' ,street = ' 四季花城 ' ,zip = ' 518003 ' ]]
生成成功(总时间:
2 秒)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值