一:关于JPA
JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分。但它又不限于EJB 3.0,你可以在Web应用、甚至桌面应用中使用。JPA的宗旨是为POJO提供持久化标准规范,由此可见,经过这几年的实践探索,能够脱离容器独立运行,方便开发和测试的理念已经深入人心了。Hibernate3.2+、TopLink 10.1.3以及OpenJPA都提供了JPA的实现。
JPA的总体思想和现有Hibernate、TopLink、JDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:
ORM映射元数据
JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
API
用来操作实体对象,执行CRUD操作,框架在后台替代我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
查询语言
这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
优势:
标准化
JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。
容器级特性的支持
JPA框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。
简单方便
JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。JPA基于非侵入式原则设计,因此可以很容易的和其它框架或者容器集成。
查询能力
JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。
高级特性
JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。
(上面的解析,来自百度文库,其实关于这个还是通过实践来更加清晰的进行了解!好了,进入实战部分)
二:构建JPA开发环境(我这里是用的Hibernate来进行演示,当然用其他的支持持久化的框架都可以哦)
步骤:(1)导入依赖
(2)创建META-INF目录和persistence.xml
为什么要创建META-INF呢?这是因为默认是需要扫描该目录的,并且该目录是放在src下面的。另外,对于这个持久化xml文件的名字也必须是pesistence.xml,这个可千万不能打错。
<?xml version="1.0"?>
<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_1_0.xsd" version="1.0">
<persistence-unit name="hnuscw" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> //注意这里面,我用的是mysql,如果你用的是oracle那么就相应的进行替换成oracle的连接驱动
<property name="hibernate.connection.username" value="xxxx" />
<property name="hibernate.connection.password" value="******" />
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/hibernatesql" />
<property name="hibernate.max_fetch_depth" value="3" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
(3)编写实体
package com.hnu.scw.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author scw
* @create 2018-01-04 17:45
* @desc 对应数据库中的person
**/
@Entity
public class Person {
@Id
@GeneratedValue
private Integer id;
private String name;
private String sex ;
/**
* 空参构造(必须要)
*/
public Person(){
}
public Person(String name , String sex){
this.name = name ;
this.sex = sex;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
(4)编写测试类
package com.hnu.scw.test;
import com.hnu.scw.model.Person;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
/**
* @author scw
* @create 2018-01-04 17:57
* @desc 进行函数测试
**/
public class JpaPersistenceTest {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("启动了");
}
/**
* 测试是否jpa测试成功
*/
@Test
public void personTest(){
//相当于获取Hibernate中的sessionFactory
EntityManagerFactory factory = Persistence.createEntityManagerFactory("hnuscw");
//相当于获取session
EntityManager entityManager = factory.createEntityManager();
//开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//进行crud操作
Person person = new Person("小吴123" , "男");
entityManager.persist(person);
//提交事务
transaction.commit();
entityManager.close();
//关闭sessionFactory
factory.close();
}
}
OK,搭建完成啦。。。。是不是很简单呢?
三:多种不同实体注解的含义和作用
1:@Id--------------表示设置该属性为数据库自增主键
2:@GeneratedValue----------表示设置该主键的自增方式,其中主要有四种:AUTO(根据数据库来自动分配),IDENTITY(mysql支持),SEQUENCE(oracle支持),TABLE(这个用得很少),另外,这个注解一般与@Id一起使用
注意:在hibernate中,如果想使用自动创建表,那么就需要指定主键的生成策略,如果不指定,就会出现,操作方法成功,但是却无法达到期望效果,比如,执行save方法,save执行成功,但是数据库却没有数据插入,就是因为主键生成策略出现问题;如果想使用已经创建表的主键策略,那么就用AUTO即可。。。(这是一个非常大的坑)
3:@Entity----------表示该实体类作为一个数据库表
4:@Table---------表示设置对应数据库中的表的名字(如果不使用就默认是该实体类名),示例如下:
@Table(name = "xxx")
public class Person {
............
..........
.......
}
5:@Column------设置属性对应数据库中字段的规范,其中可以设置字段长度,是否可以为空等信息,例如:设置name属性长度最多为10,不能为空
@Column(length = 10 ,nullable = false)
private String name;
6:@Enumerated-------设置该属性是一个枚举类,下面的例子中,SexEnum是一个性别的枚举类,这样的话,我们就可以通过下面的形式将枚举类进行设置为属性了。
@Enumerated(EnumType.ORDINAL)//这个是将枚举的索引保存到数据库,就是比如0,1,2这样的,如果就是想保存枚举类中的枚举,以字符串进行保存进数据库,那么就可以用EnumType.STRING
private SexEnum gender;
7:@Temporal--------设置日期的格式,比如有属性为Date类型,但是只是想保存为:
(1)比如2018-1-4这种格式:通过@Temporal(TemporalType.DATE)
(2)比如2018-1-4 15:08:55这种格式@Temporal(TemporalType.TIME)
(3)比如15:08:55这种格式@Temporal(TemporalType.TIMESTAMP)
比如:
@Temporal(TemporalType.DATE)
private Date birthday;
8:@Lob------设置该属性是大数据类型,比如一个文章存入到数据库,就可以把该属性用这个注解进行标识
9:@Transient--------设置该属性不作为数据库表字段进行生成,我们都知道默认一个实体中所有字段都是会存储为表的字段,但是也有情况是需要该实体某些属性不是作为数据库字段,那么就用该注解。
10:@Lob+@Basic--------设置该属性为懒加载,主要就是对于一些很大的数据量的字段内容来进行的优化,比如有一个字段该存储为5M,那其实加载这个会很花内存的,所以通过这注解就可以实现懒加载机制(一般如果某字段超过1M就应该采用这样的方式),示例如下:
@Lob @Basic(fetch = FetchType.LAZY)
private Byte[] file;
四:CRUD的基本操作(这个可以对比一下Hibernate的操作,很类似)
package com.hnu.scw.test;
import com.hnu.scw.model.Person;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.persistence.*;
import java.util.List;
/**
* @author scw
* @create 2018-01-04 17:57
* @desc 进行函数测试
**/
public class JpaPersistenceTest {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
System.out.println("启动了");
}
/**
* 测试是否jpa测试成功
*/
@Test
public void personTest(){
//相当于获取Hibernate中的sessionFactory
EntityManagerFactory factory = Persistence.createEntityManagerFactory("hnuscw");
//相当于获取session
EntityManager entityManager = factory.createEntityManager();
//开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//进行添加数据操作
/*
Person person = new Person("小吴123" , "男");
entityManager.persist(person);
*/
//========================================================
/*
//进行查询操作(不需要事务)
//方法一:下面这个相当于hibernate中的get方法,如果输入的主键是数据库中没有的,会输出null
Person person = entityManager.find(Person.class, 5);
System.out.println(person);*/
/*
//方法二:相当于hibernate中的load方法,如果输入的主键是数据库中没有的,会报异常
// (发生的时机是当进行使用结果的时候,而不是在获取加载的时候)
Person person = entityManager.getReference(Person.class, 5);
System.out.println(person);
*/
//========================================================
/*
//进行更新操作(必须要事务)
Person person = entityManager.find(Person.class, 5);
person.setName("我是更新的");
*/
//========================================================
/*
//进行删除操作
Person person = entityManager.find(Person.class, 5);
entityManager.remove(person);
*/
//========================================================
/*
//进行查询语句JPQL语句
String sql = "select p from Person p where p.id = ?";
Query query = entityManager.createQuery(sql);
query.setParameter(1 , 30);
//单条数据查询
Person personcu = (Person) query.getSingleResult();
System.out.println(personcu);
//查询多条数据
List<Person> persons = query.getResultList();
for (Person ps: persons) {
System.out.println(ps);
}*/
//提交事务
transaction.commit();
entityManager.close();
//关闭sessionFactory
factory.close();
}
}
五:一对一的编写和测试
package com.hnu.scw.model;
import javax.persistence.*;
/**
* @author scw
* @create 2018-01-08 11:52
* @desc 实体people类
**/
@Entity
public class People {
@Id
@GeneratedValue
private Integer id;
@Column(length = 10)
private String name;
@OneToOne(cascade = CascadeType.ALL ,optional = false)
@JoinColumn(name = "idcard_id")
private IDcard iDcard;
public People(){}
public People(String name){
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public IDcard getiDcard() {
return iDcard;
}
public void setiDcard(IDcard iDcard) {
this.iDcard = iDcard;
}
}
package com.hnu.scw.model;
import javax.persistence.*;
/**
* @author scw
* @create 2018-01-08 11:53
* @desc 身份证实体
**/
@Entity
public class IDcard {
@Id
@GeneratedValue
private Integer id;
@Column(length = 18)
private String numuber;
@OneToOne(cascade = CascadeType.ALL ,mappedBy = "iDcard")
private People people;
public IDcard(){}
public IDcard(String numuber){
this.numuber = numuber;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNumuber() {
return numuber;
}
public void setNumuber(String numuber) {
this.numuber = numuber;
}
public People getPeople() {
return people;
}
public void setPeople(People people) {
this.people = people;
}
}
测试类:
/**
* 测试1对1的关联关系
*/
@Test
public void one2oneTest(){
//相当于获取Hibernate中的sessionFactory
EntityManagerFactory factory = Persistence.createEntityManagerFactory("hnuscw");
//相当于获取session
EntityManager entityManager = factory.createEntityManager();
//开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
People people =new People("佘超伟");
IDcard iDcard = new IDcard("2222222222");
people.setiDcard(iDcard);
entityManager.persist(people);
transaction.commit();
entityManager.close();
factory.close();
}
六:一对多的编写和测试
package com.hnu.scw.model;
import javax.persistence.*;
import java.util.Set;
/**
* @author scw
* @create 2018-01-08 15:45
* @desc 订单实体
**/
@Entity
public class MyOrder {
@Id
@GeneratedValue
private Integer id;
@Column(length = 10)
private String name;
@OneToMany(cascade = CascadeType.ALL , mappedBy = "myOrder")
private Set<ItemOrder> itemOrders;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<ItemOrder> getItemOrders() {
return itemOrders;
}
public void setItemOrders(Set<ItemOrder> itemOrders) {
this.itemOrders = itemOrders;
}
}
package com.hnu.scw.model;
import javax.persistence.*;
/**
* @author scw
* @create 2018-01-08 15:46
* @desc 订单列表
**/
@Entity
public class ItemOrder {
@Id
@GeneratedValue
private Integer id;
@Column(length = 10)
private String itemName ;
/**
* 设置不包含remove删除的级联操作,因为订单列表删除了,但是订单不需要全部删除
*/
@ManyToOne(cascade = {CascadeType.PERSIST ,CascadeType.MERGE ,CascadeType.REFRESH} )
@JoinColumn(name = "myorder_id")
private MyOrder myOrder;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public MyOrder getMyOrder() {
return myOrder;
}
public void setMyOrder(MyOrder myOrder) {
this.myOrder = myOrder;
}
}
测试类:
/**
* 测试1对多的关联关系
*/
@Test
public void one2manyTest(){
//相当于获取Hibernate中的sessionFactory
EntityManagerFactory factory = Persistence.createEntityManagerFactory("hnuscw");
//相当于获取session
EntityManager entityManager = factory.createEntityManager();
//开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
MyOrder myOrder = new MyOrder();
myOrder.setName("我是总订单");
ItemOrder itemOrder1 = new ItemOrder();
itemOrder1.setItemName("订单列表1");
itemOrder1.setMyOrder(myOrder);
ItemOrder itemOrder2 = new ItemOrder();
itemOrder2.setItemName("订单列表2");
itemOrder2.setMyOrder(myOrder);
ItemOrder itemOrder3 = new ItemOrder();
itemOrder3.setItemName("订单列表3");
itemOrder3.setMyOrder(myOrder);
Set<ItemOrder> itemOrders = new HashSet<ItemOrder>();
itemOrders.add(itemOrder1);
itemOrders.add(itemOrder2);
itemOrders.add(itemOrder3);
//设置订单列表
myOrder.setItemOrders(itemOrders);
//执行保存
entityManager.persist(myOrder);
transaction.commit();
entityManager.close();
factory.close();
}
七:多对多的编写和测试
package com.hnu.scw.model;
import javax.persistence.*;
import java.util.Set;
/**
* @author scw
* @create 2018-01-08 16:11
* @desc 学生实体
* 备注:设置该实体为对多对端的维护端
**/
@Entity
public class Student {
@Id
@GeneratedValue
private Integer id;
@Column(length = 10)
private String name;
@ManyToMany(cascade = {CascadeType.PERSIST , CascadeType.REFRESH ,CascadeType.MERGE})
//关键注意下面的这些代码(多对多的关系通过第三张表来实现)
@JoinTable(name = "student_course" , joinColumns = @JoinColumn(name = "student_id") ,
inverseJoinColumns = @JoinColumn(name = "course_id"))
private Set<course> courses;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<course> getCourses() {
return courses;
}
public void setCourses(Set<course> courses) {
this.courses = courses;
}
}
package com.hnu.scw.model;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;
/**
* @author scw
* @create 2018-01-08 16:13
* @desc 课程实体
**/
@Entity
public class course implements Serializable{
@Id
@GeneratedValue
private Integer id;
@Column(length = 10)
private String name;
@ManyToMany(cascade = {CascadeType.PERSIST , CascadeType.REFRESH ,CascadeType.MERGE},
mappedBy = "courses")
private Set<Student> students;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
}
测试类:
/**
* 多对多的测试------------建立关系
*/
@Test
public void many2manyTest(){
//相当于获取Hibernate中的sessionFactory
EntityManagerFactory factory = Persistence.createEntityManagerFactory("hnuscw");
//相当于获取session
EntityManager entityManager = factory.createEntityManager();
//开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
Student student1 = new Student();
student1.setName("小王4");
Student student2 = new Student();
student2.setName("小黑");
course course1 = new course();
course1.setName("java");
course course2 = new course();
course2.setName("C++");
Set<course> courses1 = new HashSet<>();
Set<course> courses2 = new HashSet<>();
courses1.add(course1);
courses1.add(course2);
courses2.add(course2);
student1.setCourses(courses1);
student2.setCourses(courses2);
entityManager.persist(student1);
entityManager.persist(student2);
transaction.commit();
entityManager.close();
factory.close();
}
/**
* 多对多的关联之间的关系解除
*/
@Test
public void many2manyDeleteTest(){
//相当于获取Hibernate中的sessionFactory
EntityManagerFactory factory = Persistence.createEntityManagerFactory("hnuscw");
//相当于获取session
EntityManager entityManager = factory.createEntityManager();
//开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
Student student = entityManager.find(Student.class, 1);
entityManager.remove(student);
transaction.commit();
entityManager.close();
factory.close();
}
好了,最基本的关于JPA规范的使用通过上面这些内容,我想应该能够实现基本的使用了。当学习完这个之后,然后再去看我写的Hibernate的文章,我想应该很容易明白了。欢迎大家的关注哦~!