一、什么是JPA:
(1)JPA(Java Persistence API)即Java持久化规范,他为Java开发人员提供了一种对象/关系映射工具来管理Java应用中的关心数据,目的是结束现在Hibernate、TopLink、JDO等ORM框架各自为营的局面。JPA是在充分吸收了现有的Hibernate、TopLink、JDO等ORM框架的基础上发展而来的,具有易于使用、伸缩性强等优点。
(2)JPA的总体思想和现有Hibernate、TopLink、JDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:
①ORM映射元数据:
JPA支持XML和JDK5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
②API:
用来操作实体对象,执行CRUD操作,框架在后台替代我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
③查询语言:
这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
(3)提示:JPA不是一种新的ORM框架,他的出现只是用于规范现有的ORM技术,他不能取代现有的Hibernate、TopLink等ORM框架。相反,在采用JPA开发是,我们仍将使用到这些ORM框架,只是此时开发出来的应用不再依赖与某个持久爱化框架提供商。应用可以在不修改代码的情况下在任何JPA环境下运行,做到真正低耦合,可扩展的程序设计。
二、基于Hibernate实现JPA的简单程序:
1、导入所需要的pom.xml文件依赖:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
2、创建并编写persistence.xml文件,名称和路径都是固定的,位于类路径的META-INF目录下,如果是maven工程,则是在src/main/resources/METE-INF路径下。
<?xml version="1.0" encoding="UTF-8"?>
<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/persistence_1_0.xsd" version="1.0">
<!-- Name属性用于定义持久化单元的名字 (name必选,空值也合法); -->
<!-- transaction-type 指定事务类型(可选):本地RESOURCE_LOCAL;和全局JTA,一般用本地就可以了 -->
<persistence-unit name="jpatest" transaction-type="RESOURCE_LOCAL">
<!-- <provider>org.hibernate.ejb.HibernatePersistence</provider> -->
<properties>
<!-- 连接数据库 -->
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url"
value="jdbc:mysql://localhost:3306/jpatestdatabase?useUnicode=true&characterEncoding=UTF-8" />
<property name="hibernate.connection.username" value="root" />
<property name="hibernate.connection.password" value="admin" />
<!-- 设置数据库方言 -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<property name="hibernate.max_fetch_depth" value="3" />
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.jdbc.fetch_size" value="18" />
<property name="hibernate.jdbc.batch_size" value="10" />
</properties>
</persistence-unit>
</persistence>
persistence-uni标签的name属性:持久化单元的名字,这个属性必须要有,用来后面的EntityManagerFactory生成实例的名字。
transaction-type:使用的实物类型,默认是RESOURCE_LOCAL事务,还有一个是JTA事务。
provide:EJB Persistence provide 的一个实现类,可以分为不同的ORM,例如MyBatis和Hibernate。
properties:配置数据库厂商的属性,比如SQL-server和mysql、Oracle等。
3、创建实体类:(可以使用标签设置实体类属性)
package com.zwp.bean;
//注解标签都是是位于javax的包。
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;
import javax.persistence.Transient;
/*
@Table(name="p_table")指定数据库表名,我所导入的jar存在冲突,会抛出异常,
可以直接使用@Entity(name="p_table")来指定表名就可以解决这个问题了,
但是如果使用这种方式修改表名,就不能创建Query对象,会抛出异常。
*/
//指定需要映射的类
@Entity
public class Person {
public Person() {
}
public Person(String name) {
this.name = name;
}
private Integer id;//主键
private String name;
private Date birthday;//时间类型
private Gender gender=Gender.MAN;//枚举类型,设置默认值是MAN
private String info;//大文本类型
private Byte[] file;//二进制类型
private String imagepath;//不在数据库中生成相应的字段
//@Id,设置主键可以标注在属性上面,也可以标注在get方法上面,通常标识在get方法上面
//@GeneratedValue设置主键增长类型,AUTO是默认值,可以省略,JPA只提供整形自增长方式,没有提供uuid的增长方式
@Id @GeneratedValue(strategy=GenerationType.AUTO)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
//设置字段的规范:length,字段长度;nullable,非空;name,字段名称;
@Column(length=10,nullable=false,name="personname")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//设置时间在数据库中的格式
@Temporal(TemporalType.DATE)
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
//枚举类型
@Enumerated(EnumType.STRING) @Column(length=5,nullable=false)
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
//@Lob标明info在数据库的字段是大文本类型
@Lob
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
//@Lob标明file在数据库的字段是存放二进制类型
//@Basic(fetch=FetchType.LAZY)标识该字段延迟加载,一般用于大内存数据
@Lob @Basic(fetch=FetchType.LAZY)
public Byte[] getFile() {
return file;
}
public void setFile(Byte[] file) {
this.file = file;
}
//@Transient标明不在数据库中生成相应的字段
@Transient
public String getImagepath() {
return imagepath;
}
public void setImagepath(String imagepath) {
this.imagepath = imagepath;
}
}
枚举类:
package com.zwp.bean;
//性别的枚举
public enum Gender {
MAN,WOMEN
}
4、测试类:基本的JPA的增删改查
(1)添加Person对象:
//添加操作
@Test
public void save(){
//创建factory,方法的参数是持久化单元的名称,在此时创建数据库的表
EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
//得到EntityManager对象
EntityManager entityManager=factory.createEntityManager();
//开始事务
entityManager.getTransaction().begin();
entityManager.persist(new Person("小明"));//此时是new状态
//提交事务
entityManager.getTransaction().commit();
//关闭
entityManager.close();
factory.close();
}
(2)获取对象:
//获取数据1
@Test
public void getPerson(){
EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
EntityManager entityManager=factory.createEntityManager();
//开始事务: //读取数据是不需要开启事务的,只有需要修改数据库中的内容的时候才需要开启事务
Person person =entityManager.find(Person.class,1);//此时是managed托管状态
//执行业务操作,用了一分钟,如果有人在这个时间段更改了数据,则使用刷新方法。
entityManager.refresh(person);//刷新数据,不能重新使用find方法,因为只会去一级缓存里面找,因此不会更新数据
System.out.println(person.getName());
//关闭
entityManager.close();
factory.close();
}
//获取数据2:延迟加载
@Test
public void getPerson2(){
EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
EntityManager entityManager=factory.createEntityManager();
//延时加载:
Person person =entityManager.getReference(Person.class,1);//此时得到的是一个代理对象,没有装载数据
System.out.println(person.getName());//在访问的时候才会去装载数据,如果在person对象不存在,再此处访问会抛出异常
//关闭
entityManager.close();
factory.close();
}
(3)修改对象:
//更新操作1
@Test
public void update(){
//创建factory,方法的参数是持久化单元的名称,在此时创建数据库的表
EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
//得到EntityManager对象
EntityManager entityManager=factory.createEntityManager();
//开始事务
entityManager.getTransaction().begin();
Person person=entityManager.find(Person.class, 1);//此时实体对象是managed托管状态
person.setName("小张");//先查再修改
//提交事务
entityManager.getTransaction().commit();
//关闭
entityManager.close();
factory.close();
}
//更新操作2
@Test
public void update2(){
//创建factory,方法的参数是持久化单元的名称,在此时创建数据库的表
EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
//得到EntityManager对象
EntityManager entityManager=factory.createEntityManager();
//开始事务
entityManager.getTransaction().begin();
Person person=entityManager.find(Person.class, 1);//此时实体对象是managed托管状态
entityManager.clear();//把实体管理器中的所有实体变成游离状态
person.setName("维鹏");
entityManager.merge(person);//把实体变成托管状态,如果不变回托管状态,数据不会同步到数据库中
//提交事务
entityManager.getTransaction().commit();
//关闭
entityManager.close();
factory.close();
}
(4)删除对象:
//删除操作
@Test
public void delete(){
//创建factory,方法的参数是持久化单元的名称,在此时创建数据库的表
EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
//得到EntityManager对象
EntityManager entityManager=factory.createEntityManager();
//开始事务
entityManager.getTransaction().begin();
Person person=entityManager.find(Person.class, 1);//此时实体对象是managed托管状态
entityManager.remove(person);//先查再删
//提交事务
entityManager.getTransaction().commit();
//关闭
entityManager.close();
factory.close();
}
(5)在上面的几个测试例子中,提到了实体类的三种不同的状态,包含:New状态、manager托管状态、游离状态。感兴趣的可以自己再去了解一下。
5、测试类:JPQL语句:Query对象的增删改查:
(1)查询语句:
//JPQL:
//query查询操作:
@Test
public void query(){
EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
EntityManager entityManager=factory.createEntityManager();
entityManager.getTransaction().begin();
//取得集合对象
Query query=entityManager.createQuery("select o from Person o");
List<Person> list=query.getResultList();//得到一个集合对象,通过遍历得到里面的数据
for(Person person:list){
System.out.println(person.getName());
}
//取得单一对象
//3:表示问号的索引值
Query query1=entityManager.createQuery("select o from Person o where o.id =?3");
query1.setParameter(3, 1);//第一个参数是问号的索引,第二个参数是id值
Person person=(Person) query1.getSingleResult();//获得单一数据//相当于hibernate的session.createQuery.uniqueResult();
System.out.println(person.getName());
//取得统计对象:
Query query2=entityManager.createQuery("select count(o) from Person o");
Long lcount=(Long) query2.getSingleResult();//相当于hibernate的session.createQuery.uniqueResult();
int count=lcount.intValue();//先转成Lon类型再转成int类型
System.out.println(count);
entityManager.getTransaction().commit();
entityManager.close();
factory.close();
}
(2)修改语句:
//query修改操作:
@Test
public void updatequery(){
EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
EntityManager entityManager=factory.createEntityManager();
entityManager.getTransaction().begin();
Query query=entityManager.createQuery("update Person o set o.name=:name where o.id=:id");
query.setParameter("name", "xxx");
query.setParameter("id", 1);
query.executeUpdate();
entityManager.getTransaction().commit();
//关闭
entityManager.close();
factory.close();
}
(3)删除语句:
//query删除操作
@Test
public void deletequery(){
EntityManagerFactory factory=Persistence.createEntityManagerFactory("jpatest");
EntityManager entityManager=factory.createEntityManager();
entityManager.getTransaction().begin();
Query query=entityManager.createQuery("delete from Person o where o.id=?1");
query.setParameter(1, 1);
query.executeUpdate();
entityManager.getTransaction().commit();
//关闭
entityManager.close();
factory.close();
}
至此,一个简单的JPA增删改查程序就完成了。
这个小DEMO中,获取EntityManagerFactory对象的方式,是通过persistence.xml文件手动获取的。在下篇博客将介绍另一种获取EntityManagerFactory对象的方式,即通过Spring注入方式获取。
第二种方式可以看这篇博客:https://blog.csdn.net/a745233700/article/details/81415550
三、搭建SSH+JPA+Mysql整合项目:
SSH框架的搭建以及与Mysql数据库的整合这里就不进行介绍了,感兴趣的可以参考这篇博客:
https://blog.csdn.net/a745233700/article/details/81193652
这个主要介绍JPA与SSH的整合:
1、添加hibernate-entitymanager的maven依赖:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
2、创建并编写persistence.xml文件:
注意文件的路径和文件名,参看上面的程序写道的路径和命名(因为数据源在其他地方配置,所有该文件很简洁)
<?xml version="1.0" encoding="UTF-8"?>
<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/persistence_1_0.xsd" version="1.0">
<persistence-unit name="myjpa" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<property name="hibernate.max_fetch_depth" value="3" />
</properties>
</persistence-unit>
</persistence>
3、配置EntityManagerFactory:
数据源保持不变,但是FactoryBean由LocalSessionFactoryBean改成LocalContainerEntityManagerFactoryBean:
<!-- SSH与JPA整合:FactoryBean,由LocalSessionFactoryBean改成LocalContainerEntityManagerFactoryBean -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!-- 读取src目录下META-INF下的persistence.xml,value值是persistence-unit标签的name的值 -->
<property name="persistenceUnitName" value="myjpa"/>
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 配置JPA提供商的适配器 -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
</property>
<!-- 配置JPA基本属性 -->
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<!-- 配置实体类所在的路径 -->
<property name="packagesToScan" value="com.zwp.jpa.domain" />
</bean>
4、配置事务管理器:
<!-- SSH与JPA整合,事务管理器改为JPA的事务管理器 -->
<!-- 配置JPA的事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>
5、创建实体类进行测试:
在路径com.zwp.jpa.domain下创建实体类Student:
@Component
@Table(name="T_student")
@Entity
public class Student {
@Id
private Integer id;
private String 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;
}
}
5、部署项目,看数据库是否产生T-student表,如果有,则成功,反之,失败。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114706.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...