jpa是sun官网提出的java持久层规范,但是它不是一个持久层产品,它的实现还需要持久层产品的支持,例如hibernate,toplink等orm产品.jpa与hibernate的关系,就例如jdbc与oracle的jdbc驱动实现一样,一个是接口、规范,一个是具体的实现.
现在利用jpa接口编程,利用hibernate作为底层实现,操作oracle 11g,实现简单的增删改查
1.新建一个java工程,名为JpaHibernateOracleTest,然后将需要的jar包拷贝到工程下,如下:
这个用到的jar包 在官网下载包里面都有 前面博客曾有介绍 http://blog.csdn.net/undergrowth/article/details/9963529 只是多了一个ojdbc6.jar 这个是连接oracle数据库需要用到的jar oracle官网也有http://www.oracle.com/technetwork/cn/database/enterprise-edition/jdbc-112010-094555-zhs.html
2.建立jpa的配置文件 因为jpa在加载时 默认会在类路径下的META-INF/ 目录下查找名为persistence.xml的配置文件进行加载
所以在src目录下新建META-INF文件夹 然后在建立persistence.xml的文件
修改配置文件 在下载hibernate的解压包里面 hibernate-release-4.2.4.Final\documentation\quickstart\en-US\html_single\index.html 里面就有关于jpa配置的模板 还有一些其他的配置属性 不清楚的 查看前面博客有介绍http://blog.csdn.net/undergrowth/article/details/9963529
将persistence.xml配置文件修改如下:
<persistence 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/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="under">
<properties>
<property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver"/>
<property name="hibernate.connection.username" value="under_test" />
<property name="hibernate.connection.password" value="under_test" />
<property name="hibernate.connection.url" value="jdbc:oracle:thin:@localhost:1521:ganew" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
</properties>
</persistence-unit>
</persistence>
目前hibernate 4.2.4只支持oracle10g 虽然我用的是oracle11g 但是这里写成10g 同样可以照常工作 如果改成11g的话 hibernate不识别 会报错
3.使用注解的方式编写实体类 具体如下:
Student.java
package com.undergrowth;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
//Entity表明Student类为一个实体类 Table的name属性用于指定生成的表名
@Entity
@Table(name="studentInfo")
public class Student {
//Id用于指定id属性为实体类的主键
//GeneratedValue用于表示主键自动产生
//因为连接的是oracle数据库 所以使用序列方式产生主键
@Id @GeneratedValue(strategy=GenerationType.SEQUENCE)
private Integer id;
//Column的length指定name字段可以容纳多少个字符 nullable表示不可以为空
@Column(length=20,nullable=false)
private String name;
//以日期的格式建立该字段
@Temporal(TemporalType.DATE) @Column(nullable=false)
private Date birthday;
@Column(nullable=false)
private Integer age;
//EnumType.STRING表示存储的是枚举常量的字符串值
@Enumerated(EnumType.STRING) @Column(nullable=false,length=8)
private Gender sex;
//Lob表示大字符对象 lazy使用延迟加载
@Lob @Basic(fetch=FetchType.LAZY)
private String describe;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Gender getSex() {
return sex;
}
public void setSex(Gender sex) {
this.sex = sex;
}
public String getDescribe() {
return describe;
}
public void setDescribe(String describe) {
this.describe = describe;
}
//用于给反射使用
public Student(){}
public Student(String name, Date birthday, Integer age, Gender sex,
String describe) {
super();
this.name = name;
this.birthday = birthday;
this.age = age;
this.sex = sex;
this.describe = describe;
}
}
枚举类:
Gender.java
package com.undergrowth;
public enum Gender {
男,女
}
4.建立junit测试代码
package com.junit;
import static org.junit.Assert.*;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.Test;
public class JunitTest {
@Test
public void test() {
//通过配置文件中的<persistence-unit name="under">持久单元名,获取实体管理器工厂
EntityManagerFactory factory=Persistence.createEntityManagerFactory("under");
//关闭实体管理器工厂
factory.close();
}
}
在test测试方法中加入以上两句话 就可测试环境是否已经成功搭建 并且建立表结构 也是在创建实体管理器工厂的时候
如果没有问题 在oracle数据库中 应该看到studentinfo的表结构 如下
产生主键的序列:
现在接着修改测试的test函数 实现增删改查
修改如下:
添加记录
package com.junit;
import static org.junit.Assert.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.Test;
import com.undergrowth.Gender;
import com.undergrowth.Student;
public class JunitTest {
@Test
public void test() {
//通过配置文件中的<persistence-unit name="under">持久单元名,获取实体管理器工厂
EntityManagerFactory factory=Persistence.createEntityManagerFactory("under");
//获取管理器实体
EntityManager manager=factory.createEntityManager();
try {
addStudent(manager);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//关闭管理器实体
manager.close();
//关闭实体管理器工厂
factory.close();
}
private void addStudent(EntityManager manager) throws ParseException {
// TODO Auto-generated method stub
//打开事务
manager.getTransaction().begin();
Student student=new Student("undergrowth", new SimpleDateFormat("yyyy-MM-dd").parse("1999-1-2"), 20, Gender.男, "读书");
manager.persist(student);
//提交事务
manager.getTransaction().commit();
}
}
控制台输出:
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into studentInfo (age, birthday, name, sex, id, describe) values (?, ?, ?, ?, ?, ?)
通过控制台输出可以看到 hibernate底层使用了插入语句
oracle 数据效果
剩下的删除、更新、查询如下:
package com.junit;
import static org.junit.Assert.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.Test;
import com.undergrowth.Gender;
import com.undergrowth.Student;
public class JunitTest {
@Test
public void test() {
//通过配置文件中的<persistence-unit name="under">持久单元名,获取实体管理器工厂
EntityManagerFactory factory=Persistence.createEntityManagerFactory("under");
//获取管理器实体
EntityManager manager=factory.createEntityManager();
/*try {
addStudent(manager);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
//调用更新
updateStudent(manager);
//关闭管理器实体
manager.close();
//关闭实体管理器工厂
factory.close();
}
private void addStudent(EntityManager manager) throws ParseException {
// TODO Auto-generated method stub
//打开事务
manager.getTransaction().begin();
Student student=new Student("undergrowth", new SimpleDateFormat("yyyy-MM-dd").parse("1999-1-2"), 20, Gender.男, "读书");
manager.persist(student);
//提交事务
manager.getTransaction().commit();
}
private Student selectStudent(EntityManager manager) {
// TODO Auto-generated method stub
//通过实体类的主键找到实体类
Student student=manager.find(Student.class, 270);
return student;
}
private void updateStudent(EntityManager manager) {
// TODO Auto-generated method stub
//打开事务
manager.getTransaction().begin();
Student student=selectStudent(manager);
student.setName("刘德华"); //处于事务管理关联并且实体类处于托管状态 才可以更新到数据库中
//提交事务
manager.getTransaction().commit();
}
}
控制台输出:
Hibernate: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.birthday as birthday3_0_0_, student0_.describe as describe4_0_0_, student0_.name as name5_0_0_, student0_.sex as sex6_0_0_ from studentInfo student0_ where student0_.id=?
Hibernate: update studentInfo set age=?, birthday=?, name=?, sex=?, describe=? where id=?
oracle 效果图:
删除:
package com.junit;
import static org.junit.Assert.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.junit.Test;
import com.undergrowth.Gender;
import com.undergrowth.Student;
public class JunitTest {
@Test
public void test() {
//通过配置文件中的<persistence-unit name="under">持久单元名,获取实体管理器工厂
EntityManagerFactory factory=Persistence.createEntityManagerFactory("under");
//获取管理器实体
EntityManager manager=factory.createEntityManager();
/*try {
addStudent(manager);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
//调用更新
//updateStudent(manager);
//删除
deleteStudent(manager);
//关闭管理器实体
manager.close();
//关闭实体管理器工厂
factory.close();
}
private void addStudent(EntityManager manager) throws ParseException {
// TODO Auto-generated method stub
//打开事务
manager.getTransaction().begin();
Student student=new Student("undergrowth", new SimpleDateFormat("yyyy-MM-dd").parse("1999-1-2"), 20, Gender.男, "读书");
manager.persist(student);
//提交事务
manager.getTransaction().commit();
}
private Student selectStudent(EntityManager manager) {
// TODO Auto-generated method stub
//通过实体类的主键找到实体类
Student student=manager.find(Student.class, 270);
return student;
}
private void updateStudent(EntityManager manager) {
// TODO Auto-generated method stub
//打开事务
manager.getTransaction().begin();
Student student=selectStudent(manager);
student.setName("刘德华"); //处于事务管理关联并且实体类处于托管状态 才可以更新到数据库中
//提交事务
manager.getTransaction().commit();
}
private void deleteStudent(EntityManager manager) {
// TODO Auto-generated method stub
//打开事务
manager.getTransaction().begin();
Student student=selectStudent(manager);
manager.remove(student); //处于事务管理关联并且实体类处于托管状态 才可以更新到数据库中
//提交事务
manager.getTransaction().commit();
}
}
控制台:
Hibernate: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.birthday as birthday3_0_0_, student0_.describe as describe4_0_0_, student0_.name as name5_0_0_, student0_.sex as sex6_0_0_ from studentInfo student0_ where student0_.id=?
Hibernate: delete from studentInfo where id=?
对于查询的话 除了find以外 还可使用getReference
对于更新与删除 能够与数据库同步的原因在于
第一:实体对象处于实体对象管理器之下,即实体对象处于托管状态
第二: 实体管理器与事务关联
二者缺一 实体对象都没有办法与数据库同步
以上即是jpa的简单实现 记录学习的脚步 好晚了 睡觉了