JPA学习总结

来源:互联网 发布:linux i2c总线驱动 编辑:程序博客网 时间:2024/05/16 08:09

一、什么是JPA: 

   JPA(Java Persistence API)是SUN官方提出的Java持久化规范。它为java开发人员提供了一种对象/关系映射工具来管理Java应用中的关系数据。他的出现主要是为简化现有的持久化开发工作和整合ORM技术,结束现在Hibernate、TopLink、JDO等ORM框架各自为营的局面。值得注意的是,JPA是在充分吸收现有HIbernate、TopLink、JDO等ORM框架的基础上发展而来的,具有易于使用、伸缩性强等优点。

    JPA的总体思想和现有Hibernate、TopLink、JDO等ORM框架大体一致。总的来说包括以下三种技术:

  • ORM映射元数据
 JPA支持XML和JDK5.0注释两种元数据的形式,元数据(注释)描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中。
  • Java持久化API
 用来操作实体对象,执行GRUD操作,框架在后台替我们完成所有的事情,开发者可以从繁琐的JDBC和SQL代码中解脱出来。
  • 查询语言
 这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合
提示:JPA不是一种新的ORM框架,他的出现只是在用于规范现有的ORM技术,他不能取代现有的Hibernate、TopLink等ORM框架。相反,在采用JPA开发时,我们仍将使用到这些ORM框架。只是此时开发出来的应用不再依赖与某个持久化提供商,应用可以在不修改代码的情况下在任何JPA环境下运行,真正做到低耦合,可扩展的程序设计。

二、JPA开发环境和思想介绍:

 1.1需要的jar包:

 

1.2、JPA配置文件:
JPA规范要求在类路径的META-INF目录下放置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_1_0.xsd"
version="1.0">
<persistence-unit name="sample" transaction-type="RESOURCE_LOCAL">

<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.url" value="jdbc:mysql://127.0.0.1:3306/springTest?useUnicode=true&;characterEncoding=gb2312"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.max_fetch_depth" value="3"/>
</properties>
</persistence-unit>
</persistence>

1.3、JPA实体类的定义以及一些注释:
定义实体类:@Entity @Table(name = "students")
定义时间类型:@Temporal(TemporalType.DATE)
定义主键生成器:@Id @GeneratedValue(strategy = GenerationType.AUTO)
定义普通属性:@Column(name = "student_name", nullable = false, length = 20, unique = true)
定义枚举类型的映射: @Enumerated(EnumType.STRING) Column(name="sex",length=4,nullable=false)
定义不是持久化属性:@Transient
定义大数据类型注解:@log
@Basic是懒加载注解,只有去调用此属性的时候数据库才会把数据转载到内存中去


2、实现JPA的增删改查功能,JQL的查询功能(基于面向对象的查询):

2.1、获得数据库的链接:
//取得实体管理工厂
EntityManagerFactory managerFactory=Persistence.createEntityManagerFactory("sample")
//创建实体管理对象
EntityManager em=managerFactory.createEntityManager();

2.2、保存数据:
//创建实体管理工厂
managerFactory=Persistence.createEntityManagerFactory("sample");
//通过实体工厂创建实体管理器
em=managerFactory.createEntityManager();
//打开事物
em.getTransaction().begin();
//保存数据
em.persist(new Student("小明1",20,new Date()));
em.getTransaction().commit();
em.close();

2.3、获取数据:

2.3.1、find获取数据方法:
//创建实体管理工厂
managerFactory=Persistence.createEntityManagerFactory("sample");
//通过实体工厂创建实体管理器
em=managerFactory.createEntityManager();
//Student指定要查找的实体Bean,1:表示实体Bean的标识符
student=em.find(Student.class,i);
em.close();
managerFactory.close();

2.3.2、getReferences获取数据:
Student student=null;
//创建实体管理工厂
managerFactory=Persistence.createEntityManagerFactory("sample");
//通过实体工厂创建实体管理器
em=managerFactory.createEntityManager();
//使用getReference()方法返回的是代理对象,只有在调用数据的时候才会发生装载行为
student=em.getReference(Student.class,1);

****************JQL查询*************

String jql="select o from Student o where o.name=?1";

Query query=em.createQuery(jql);

query.setParameter(1, "小明");

     List<Student> students=query.getResultList();

     Student student1=(Student)query.getSingleResult();

em.close();
managerFactory.close();

************************************

2.4更新数据:
//创建实体管理工厂
managerFactory=Persistence.createEntityManagerFactory("sample");
//通过实体工厂创建实体管理器
em=managerFactory.createEntityManager();
//打开事物
em.getTransaction().begin();

student.setName("小花");
student.setGender(Gender.女);
em.merge(student);
em.getTransaction().commit();

****************JQL查询*************
String jql="update Student o set o.name=:name,o.age=:age where o.id=:id";
Query query=em.createQuery(jql);
query.setParameter("name", "张三");
query.setParameter("age",20);
query.setParameter("id", 2);
int i=query.executeUpdate();
System.out.println("数据库受影响行数:"+i);

em.close();

managerFactory.close();


************************************

2.5、删除数据:
//创建实体管理工厂
managerFactory=Persistence.createEntityManagerFactory("sample");
//通过实体工厂创建实体管理器
em=managerFactory.createEntityManager();
//打开事物
em.getTransaction().begin();
student=em.find(Student.class,2);

em.remove(student);


****************JQL查询*************

String jql="delete from Student o  where o.id=:id";

Query query=em.createQuery(jql);

query.setParameter("id", 2);

int i=query.executeUpdate();

System.out.println("数据库受影响行数:"+i);

em.getTransaction().commit();

em.close();
managerFactory.close();

************************************

三、JPA关联关系:

谨记一句话:如果(1-M) 则多的一方为关系维护端。关系维护端 负责外键记录的更新及定义,关系被维护端是没有权利更新外键

1、一对多的双向关联:
关系被维护端:

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.CascadeType;
import javax.persistence.Table;

/**
* 订单类

* @author Administrator

*/
@Entity
@Table(name = "orders")

public class Order {
private String orderCode;
private float amount = 0f;
private Set<OrderItem> items = new HashSet<OrderItem>();

@Id
@Column(length = 12)

public String getOrderCode() {
return orderCode;
}

public void setOrderCode(String orderCode) {
this.orderCode = orderCode;
}

@Column(nullable = false)
public float getAmount() {
return amount;
}

public void setAmount(float amount) {
this.amount = amount;
}

@OneToMany(cascade = { CascadeType.REFRESH, CascadeType.PERSIST,
CascadeType.MERGE, CascadeType.REMOVE }, mappedBy = "order")

public Set<OrderItem> getItems() {
return items;
}

public void setItems(Set<OrderItem> items) {
this.items = items;
}
public void addOrderItem(OrderItem orderItem,float price)
{ orderItem.setOrder(this);
orderItem.setPrice(price);
items.add(orderItem);
}
}
关系维护端:

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
/**
* 订单项

* @author Administrator

*/
@Entity
public class OrderItem {

private int id;
private float price = 0f;
private String name;
private Order order;
@Id
@GeneratedValue

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(nullable = false)
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
@ManyToOne(cascade = { CascadeType.REFRESH, CascadeType.MERGE }, optional = false)
@JoinColumn(name = "order_id")

public Order getOrder() {
return order;
}

public void setOrder(Order order) {

this.order = order;

}

@Column(length=20,nullable=false)

public String getName() {

return name;

}

2、一对一的关联关系:

关系维护端:

@Entity
public class Person {
private int id;
private String name;
private IDCard idCard;
@OneToOne(cascade={CascadeType.ALL},optional=false)
@JoinColumn(name="idCard_id")
public IDCard getIdCard() {
return idCard;
}
public void setIdCard(IDCard idCard) {
this.idCard = idCard;
}
@Id @GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(length=10,nullable=false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

关系被维护端:

@Entity

public class IDCard {

private int id;

private String IDCardCode;

private Date userlife;

private Person person;

@OneToOne(cascade={CascadeType.REFRESH,CascadeType.MERGE,CascadeType.PERSIST},mappedBy="idCard")

public Person getPerson() {

return person;

}

public void setPerson(Person person) {

this.person = person;

}

@Id @GeneratedValue

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

@Column(length=18,nullable=false)

public String getIDCardCode() {

return IDCardCode;

}

public void setIDCardCode(String iDCardCode) {

IDCardCode = iDCardCode;

}

@Temporal(TemporalType.DATE)

public Date getUserlife() {

return userlife;

}

public void setUserlife(Date userlife) {

this.userlife = userlife;

}

4、多对多的关联关系:

/**

 * 多对多被维护端

 * @author Administrator

 *

 */

@Entity(name="students_1")

public class Students {

private int id;

private String name;

private List<Teachers> teachers=new ArrayList<Teachers>();

@ManyToMany(cascade={CascadeType.REFRESH},mappedBy="students")

public List<Teachers> getTeachers() {

return teachers;

}

public void setTeachers(List<Teachers> teachers) {

this.teachers = teachers;

}

@Id @GeneratedValue

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

@Column(length=20,nullable=false)

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

关系维护端:

/**

 * 多对多维护端

 * @author Administrator

 *

 */

@Entity

public class Teachers {

private int id;

private String name;

private List<Students> students=new ArrayList<Students>();

@ManyToMany(cascade={CascadeType.REFRESH})

@JoinTable(name="teachers_students",inverseJoinColumns=@JoinColumn(name="students_code"),joinColumns=@JoinColumn(name="teacher_code"))

public List<Students> getStudents() {

return students;

}

public void setStudents(List<Students> students) {

this.students = students;

}

@Id @GeneratedValue

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

@Column(length=20,nullable=false)

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

//建立与学生的关系

public void addStudent(Students student)

{

this.students.add(student);

}

//删除与学生之间的关系

public void removeStudent(Students student)

{  

if(this.students.contains(student))

{  

this.students.remove(student);

}

}

5、复合主键的应用:


1.1、先定义一个复合主键类,其要求:必须继承接口Serializeable、使用@
@Embeddable注解该类、必须有一个public的无参构造方法、重载hashcode(),equals()方法

@Embeddable

public class CarPK implements Serializable{

private String startSite;

private String endSite;

public CarPK(){}

public CarPK(String startSite,String endSite)

{

this.startSite=startSite;

this.endSite=endSite;

}

public String getStartSite() {

return startSite;

}

public void setEndSite(String endSite) {

this.endSite = endSite;

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + ((endSite == null) ? 0 : endSite.hashCode());

result = prime * result + ((startSite == null) ? 0 : startSite.hashCode());

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

CarPK other = (CarPK) obj;

if (endSite == null) {

if (other.endSite != null)

return false;

} else if (!endSite.equals(other.endSite))

return false;

if (startSite == null) {

if (other.startSite != null)

return false;

} else if (!startSite.equals(other.startSite))

return false;

return true;

}


public void setStartSite(String startSite) {

this.startSite = startSite;

}

public String getEndSite() {

return endSite;

}

1.2、如何使用该复合主键类呢?

@Entity

public class CarLine {

private CarPK id;

private String lineName;

private float price=0f;

public CarLine()

{

}

public CarLine(CarPK id)

{

this.id=id;

}

public CarLine(String startSite,String endSite,String lineName,float price)

{

this.id=new CarPK(startSite,endSite);

this.lineName=lineName;

this.price=price;

}

@EmbeddedId

public CarPK getId() {

return id;

}

public void setId(CarPK id) {

this.id = id;

}

@Column(length=20)

public String getLineName() {

return lineName;

}

public void setLineName(String lineName) {

this.lineName = lineName;

}

@Column(nullable=false)

public float getPrice() {

return price;

}

public void setPrice(float price) {

this.price = price;

}

}

主意事项:在定义一个实体bean时最好继承Serialable接口,那么为什么要实现此接口呢?

答:首先JPA(Hibernate)框架使用的是反射技术,反射里面就存在输入、输出流的东西所以实体类需要序列化,序列化的好处就是方便读写和网络传输这个在某些事时候是非常有必要的为了考虑到以后的扩展性.一般都实现序列化.