详谈hibernate,jpa与spring data jpa三者之间的关系

前提

其实很多框架都是对另一个框架的封装,我们在学习类似的框架的时候,难免会进入误区,所以我们就应该对其进行总结归纳,对比。本文就是对hibernate,jpa,spring data jpa三者之间进行文字对比,以及对其三者分别进行CRUD操作。

文字说明

Hibernate

Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。

JPA

JPA全称是Java Persistence API,即java持久化API,是sun公司推出的一套基于ORM的规范,内部由一系列的接口和抽象类构成。

JPA与Hibetnate的关系

JPA和Hibernate的关系就像JDBC和JDBC驱动的关系,JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现。JPA怎么取代Hibernate呢?JDBC规范可以驱动底层数据库吗?答案是否定的,也就是说,如果使用JPA规范进行数据库操作,底层需要hibernate作为其实现类完成数据持久化工作。

Spring Data jpa

Spring Data JPA 让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它来实现,在实际的工作工程中,推荐使用Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的ORM框架时提供了极大的方便,同时也使数据库层操作更加简单,方便解耦

Hibernate、JPA与Spring Data JPA之间的关系

JPA是一套规范,内部是有接口和抽象类组成的。hibernate是一套成熟的ORM框架,而且Hibernate实现了JPA规范,所以也可以称hibernate为JPA的一种实现方式,我们使用JPA的API编程,意味着站在更高的角度上看待问题(面向接口编程)Spring Data JPA是Spring提供的一套对JPA操作更加高级的封装,是在JPA规范下的专门用来进行数据持久化的解决方案。以上就是对hibernate、JPA与Spring Data JPA三者之间的关系说明。

总结:

JPA是一种规范,Hibernate实现了JPA规范,即Hibernate为JPA的一种实现;而Spring Data JPA是对JPA进行更高级的封装,让其dao编码变得更简单。

CRUD操作

hibernate的crud操作

首先创建数据库表

在这里插入图片描述

创建hibernate核心配置文件hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC

"-//Hibernate/Hibernate Configuration DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>

<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

<property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>

<property name="hibernate.connection.username">root</property>

<property name="hibernate.connection.password">root</property>

<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>

<property name="hibernate.show_sql">true</property>

<property name="hibernate.format_sql">true</property>

<property name="hibernate.hbm2ddl.auto">update</property>

<!-- 配置和当前线程绑定的session进行开启配置 -->

<property name="hibernate.current_session_context_class">thread</property>

<!-- 引入映射文件 -->

<mapping resource="cn/itcast/domain/Customer.hbm.xml" />

</session-factory>

</hibernate-configuratio

创建实体类Customer(和数据库表映射的类)

package cn.itcast.domain;

public class Customer

{

private Long cust_id;// '客户编号(主键)',

private String cust_name;// '客户名称(公司名称)',

private String cust_source;// '客户信息来源',

private String cust_industry;//'客户所属行业',

private String cust_level;// '客户级别',

private String cust_address;// '客户联系地址',

private String cust_phone;// '客户联系电话',

public Long getCust_id() {

return cust_id;

}

public void setCust_id(Long cust_id) {

this.cust_id = cust_id;

}

public String getCust_name() {

return cust_name;

}

public void setCust_name(String cust_name) {

this.cust_name = cust_name;

}

public String getCust_source() {

return cust_source;

}

public void setCust_source(String cust_source) {

this.cust_source = cust_source;

}

public String getCust_industry() {

return cust_industry;

}

public void setCust_industry(String cust_industry) {

this.cust_industry = cust_industry;

}

public String getCust_level() {

return cust_level;

}

public void setCust_level(String cust_level) {

this.cust_level = cust_level;

}

public String getCust_address() {

return cust_address;

}

public void setCust_address(String cust_address) {

this.cust_address = cust_address;

}

public String getCust_phone() {

return cust_phone;

}

public void setCust_phone(String cust_phone) {

this.cust_phone = cust_phone;

}

}

创建Hibernate映射文件Customer.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<!-- 做类(Customer)和表(cst_customer)的映射关系 -->

<hibernate-mapping>

<!--

class标签: 作用类和表的映射的

name:类的全限定名(cn.itcast.domain.Customer)

table:表的全名(cst_customer)

-->

<class name="cn.itcast.domain.Customer" table="cst_customer">

<!--

id标签:做类中的某个属性 和 表的主键映射关系

name:类的某个属性名

column:表的主键字段名

-->

<id name="cust_id" column="cust_id">

<!-- 做主键的增长方式的

native: AUTO_INCREMENT 让主键自动增长 -->

<generator class="native"></generator>

</id>

<!--

property标签:做其它属性和其它字段的映射关系

name属性:类的其它属性名

column属性:表的其它字段名

ps:如果属性名和字段名一致 column可以省略不写

-->

<property name="cust_name" column="cust_name" length="20" not-null="true" unique="true"></property>

<property name="cust_source" column="cust_source"></property>

<property name="cust_industry" column="cust_industry"></property>

<property name="cust_level" column="cust_level"></property>

<property name="cust_address" column="cust_address"></property>

<property name="cust_phone" column="cust_phone"></property>

</class>

</hibernate-mapping>

以上我们就完成了dao层的编码工作。现在我们来测试:

创建工具类HibernateUtils

package cn.itcast.utils;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

public class HibernateUtils

{

static Configuration configuration =null;

static SessionFactory sessionFactory = null;

static

{

// 加载一次配置文件

configuration = new Configuration();

configuration.configure();

// 获取一个sessionFactory

sessionFactory=configuration.buildSessionFactory();

}

// 从连接池获取的

public static Session openSession()

{

return sessionFactory.openSession();

}

// 从当前线程中获取绑定的session

// 好处: 在多层之间调用方法获取的都是同一个session

public static Session getCurrentSession()

{

/*特点: 1 默认是关闭的 需要配置开启

2 会自动给你关闭连接*/

Session session = sessionFactory.getCurrentSession();

return session;

}

}

通过以上工具类,我们就可以轻松地获取管理hibernate的seesion对象,session对象具备crud的一系列方法。

save():保存操作

@Test

public void test2()

{

Session session = HibernateUtils.openSession();

Transaction tx = session.beginTransaction();

Customer customer = new Customer();

customer.setCust_name("bbbbb");

session.save(customer);

tx.commit();

session.close();

}

get():查询

// oid查询

@Test

public void test1() {

Session session = HibernateUtils.openSession();

Transaction tx = session.beginTransaction();

Customer customser = session.get(Customer.class, "abcdefg");

System.out.println(customser);

tx.commit();

session.close();

// 只有增删改 一级oid查询 才会自动生成sql语句

}

通过HQL方式查询:

@Test

public void test3() {

Session session = HibernateUtils.openSession();

Transaction tx = session.beginTransaction();

// 条件查 类似sql语句的表达式 from 持久化类 where 属性=?

Query qr = session.createQuery("from Customer where cust_name like ?");

qr.setParameter(0, "h%");

List<Customer> list = qr.list();

for (Customer customer : list) {

System.out.println(customer);

}

tx.commit();

session.close();

}

通过sql方式查询:

@Test

public void test5() {

Session session = HibernateUtils.openSession();

Transaction tx = session.beginTransaction();

// 单列查 返回是Object

Query qr = session.createQuery("select cust_id from Customer");

List<Object> list = qr.list();

for (Object object : list) {

System.out.println(object);

}

tx.commit();

session.close();

}

JPA的crud操作

该操作我们用maven的方式来构建依赖

首先我们需要引入依赖:

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<project.hibernate.version>5.0.7.Final</project.hibernate.version>

</properties>

<dependencies>

<!-- junit -->

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.12</version>

<scope>test</scope>

</dependency>

<!-- hibernate对jpa的支持包 -->

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-entitymanager</artifactId>

<version>${project.hibernate.version}</version>

</dependency>

<!-- c3p0 -->

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-c3p0</artifactId>

<version>${project.hibernate.version}</version>

</dependency>

<!-- log日志 -->

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>1.2.17</version>

</dependency>

<!-- Mysql and MariaDB -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.6</version>

</dependency>

</dependencies>

在这里插入图片描述

在resources目录下创建META-INF目录,并在该目录下创建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

http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"

version="2.0">

<!--配置持久化单元

name:持久化单元名称

transaction-type:事务类型

RESOURCE_LOCAL:本地事务管理

JTA:分布式事务管理 -->

<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">

<!--配置JPA规范的服务提供商 -->

<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

<properties>

<!-- 数据库驱动 -->

<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />

<!-- 数据库地址 -->

<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa?characterEncoding=utf-8" />

<!-- 数据库用户名 -->

<property name="javax.persistence.jdbc.user" value="root" />

<!-- 数据库密码 -->

<property name="javax.persistence.jdbc.password" value="root" />

<!--jpa提供者的可选配置:我们的JPA规范的提供者为hibernate,所以jpa的核心配置中兼容hibernate的 -->

<!--配置jpa实现方(hibernate)的配置信息

显示sql : false|true

自动创建数据库表 : hibernate.hbm2ddl.auto

create : 程序运行时创建数据库表(如果有表,先删除表再创建)

update :程序运行时创建表(如果有表,不会创建表)

none :不会创建表

-->

<property name="hibernate.show_sql" value="true" />

<property name="hibernate.format_sql" value="true" />

<property name="hibernate.hbm2ddl.auto" value="create" />

</properties>

</persistence-unit>

</persistence>

创建和数据库表映射的实体类

package com.ithubei.entity;

import java.io.Serializable;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.Table;

/**

* @Entity

作用:指定当前类是实体类。

@Table

作用:指定实体类和表之间的对应关系。

属性:

name:指定数据库表的名称

@Id

作用:指定当前字段是主键。

@GeneratedValue

作用:指定主键的生成方式。。

属性:

strategy :指定主键生成策略。

@Column

作用:指定实体类属性和数据库表之间的对应关系

属性:

name:指定数据库表的列名称。

unique:是否唯一

nullable:是否可以为空

inserttable:是否可以插入

updateable:是否可以更新

columnDefinition: 定义建表时创建此列的DDL

secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字搭建开发环境[重点]

* @author DELL

*

*/

@Entity //声明该类是和数据库表映射的实体类

@Table(name="cst_customer") //建立实体类与表的映射关系

public class Customer implements Serializable{

@Id //声明当前私有属性为主键

@GeneratedValue(strategy=GenerationType.IDENTITY) //配置主键的生成策略,为自增主键

@Column(name = "cust_id")

private Long custId;

@Column(name="cust_name") //指定和表中cust_name字段的映射关系

private String custName;

@Column(name="cust_source") //指定和表中cust_source字段的映射关系

private String custSource;

@Column(name="cust_industry")

private String custIndustry;

@Column(name="cust_level")

private String custLevel;

@Column(name="cust_address")

private String custAddress;

@Column(name="cust_phone")

private String custPhone;

public Long getCustId() {

return custId;

}

public void setCustId(Long custId) {

this.custId = custId;

}

public String getCustName() {

return custName;

}

public void setCustName(String custName) {

this.custName = custName;

}

public String getCustSource() {

return custSource;

}

public void setCustSource(String custSource) {

this.custSource = custSource;

}

public String getCustIndustry() {

return custIndustry;

}

public void setCustIndustry(String custIndustry) {

this.custIndustry = custIndustry;

}

public String getCustLevel() {

return custLevel;

}

public void setCustLevel(String custLevel) {

this.custLevel = custLevel;

}

public String getCustAddress() {

return custAddress;

}

public void setCustAddress(String custAddress) {

this.custAddress = custAddress;

}

public String getCustPhone() {

return custPhone;

}

public void setCustPhone(String custPhone) {

this.custPhone = custPhone;

}

}

创建工具类JpaUtils

package com.ithubei.utils;

import javax.persistence.EntityManager;

import javax.persistence.EntityManagerFactory;

import javax.persistence.Persistence;

/**

* 解决实体管理器工厂的浪费资源和耗时问题

* 通过静态代码块的形式,当程序第一次访问此工具类时,创建一个公共的实体管理器工厂对象

*

* 第一次访问getEntityManager方法:经过静态代码块创建一个factory对象,再调用方法创建一个EntityManager对象

* 第二次方法getEntityManager方法:直接通过一个已经创建好的factory对象,创建EntityManager对象

*/

public class JpaUtils {

private static EntityManagerFactory entityManagerFactory;

static {

//1.加载配置文件,创建entityManagerFactory

entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");

}

public static EntityManager getEntityManager() {

return entityManagerFactory.createEntityManager();

}

}

通过以上工具类,我们就可以得到EntityManager实体管理类来进行crud等操作。

在 JPA 规范中, EntityManager是完成持久化操作的核心对象。实体类作为普通 java对象,只有在调用 EntityManager将其持久化后才会变成持久化对象。EntityManager对象在一组实体类与底层数据源之间进行 O/R 映射的管理。它可以用来管理和更新 Entity Bean, 根椐主键查找 Entity Bean, 还可以通过JPQL语句查询实体。

我们可以通过调用EntityManager的方法完成获取事务,以及持久化数据库的操作。

方法说明:

  • getTransaction:获取事务对象
  • persist:保存操作
  • merge:更新操作
  • remove:删除操作
  • find(立即加载)/getReference(延迟加载):根据id查询

现在我们就来通过EntityManager对象来进行crud操作。

测试:

package com.ithubei.test;

import javax.persistence.EntityManager;

import javax.persistence.EntityTransaction;

import org.junit.Test;

import com.ithubei.entity.Customer;

import com.ithubei.utils.JpaUtils;

public class JpaTest {

/**

* 保存操作

*/

@Test

public void testSave() {

//通过工具类来获取EntityManager对象

EntityManager em = JpaUtils.getEntityManager();

//获取事务对象

EntityTransaction tx = em.getTransaction();

tx.begin(); //开启事务

//完成增删改查操作,保存一个用户到数据库中

Customer customer = new Customer();

customer.setCustName("授课");

customer.setCustIndustry("教育");

//保存操作

em.persist(customer);

tx.commit(); //提交事务

em.close(); //释放资源

}

/**

* 保存一个实体

*/

@Test

public void testAdd() {

// 定义对象

Customer c = new Customer();

c.setCustName("传智学院");

c.setCustLevel("VIP客户");

c.setCustSource("网络");

c.setCustIndustry("IT教育");

c.setCustAddress("昌平区北七家镇");

c.setCustPhone("010-84389340");

EntityManager em = null;

EntityTransaction tx = null;

try {

// 获取实体管理对象

em = JpaUtils.getEntityManager();

// 获取事务对象

tx = em.getTransaction();

// 开启事务

tx.begin();

// 执行操作

em.persist(c);

// 提交事务

tx.commit();

} catch (Exception e) {

// 回滚事务

tx.rollback();

e.printStackTrace();

} finally {

// 释放资源

em.close();

}

}

/**

* 修改操作

*/

@Test

public void testMerge(){

//定义对象

EntityManager em=null;

EntityTransaction tx=null;

try{

//获取实体管理对象

em=JpaUtils.getEntityManager();

//获取事务对象

tx=em.getTransaction();

//开启事务

tx.begin();

//执行操作

Customer c1 = em.find(Customer.class, 6L);

c1.setCustName("江苏传智学院");

em.clear();//把c1对象从缓存中清除出去

em.merge(c1);

//提交事务

tx.commit();

}catch(Exception e){

//回滚事务

tx.rollback();

e.printStackTrace();

}finally{

//释放资源

em.close();

}

}

/**

* 删除操作

*/

@Test

public void testRemove() {

// 定义对象

EntityManager em = null;

EntityTransaction tx = null;

try {

// 获取实体管理对象

em = JpaUtils.getEntityManager();

// 获取事务对象

tx = em.getTransaction();

// 开启事务

tx.begin();

// 执行操作

Customer c1 = em.find(Customer.class, 6L);

em.remove(c1);

// 提交事务

tx.commit();

} catch (Exception e) {

// 回滚事务

tx.rollback();

e.printStackTrace();

} finally {

// 释放资源

em.close();

}

}

/**

* 查询操作find()

*/

@Test

public void testGetOne() {

// 定义对象

EntityManager em = null;

EntityTransaction tx = null;

try {

// 获取实体管理对象

em = JpaUtils.getEntityManager();

// 获取事务对象

tx = em.getTransaction();

// 开启事务

tx.begin();

// 执行操作

Customer c1 = em.find(Customer.class, 96);

// 提交事务

tx.commit();

System.out.println(c1); // 输出查询对象

} catch (Exception e) {

// 回滚事务

tx.rollback();

e.printStackTrace();

} finally {

// 释放资源

em.close();

}

}

}

虽然我们已经使用EntityManager对象完成了JPA的新增改查操作,但是我们这里还要介绍另外一种查询方式,那就是JPQL(java持久化查询语言),JPQL与hibernate的HQL方式类似。

package com.ithubei.test;

import java.util.List;

import javax.persistence.EntityManager;

import javax.persistence.EntityTransaction;

import javax.persistence.Query;

import org.junit.Test;

import com.ithubei.utils.JpaUtils;

/**

* 使用JPQL(java持久化查询语言)来查询数据

* @author DELL

*

*/

public class JpqlTest {

/**

* 查询全部的客户

*/

@Test

public void findAll() {

EntityManager em = null;

EntityTransaction tx = null;

try {

//获取是管理对象

em = JpaUtils.getEntityManager();

//获取事务对象

tx = em.getTransaction();

//开启事务

tx.begin();

String jpql = "from Customer";

//创建query对象

Query query = em.createQuery(jpql);

//使用query对象查询客户信息

List list = query.getResultList(); //查询所有的客户

for (Object object : list) {

System.out.println(object);

}

//提交事务

tx.commit();

}catch (Exception e) {

// TODO: handle exception

//发生异常进行回滚

tx.rollback();

e.printStackTrace();

}finally {

//释放资源

em.close();

}

}

//分页查询客户

@Test

public void findPaged () {

EntityManager em = null;

EntityTransaction tx = null;

try {

//获取实体管理对象

em = JpaUtils.getEntityManager();

//获取事务对象

tx = em.getTransaction();

tx.begin();

//创建query对象

String jpql = "from Customer";

Query query = em.createQuery(jpql);

//起始索引

query.setFirstResult(0);

//每页显示条数

query.setMaxResults(2);

//查询并得到返回结果

List list = query.getResultList(); //得到集合返回类型

for (Object object : list) {

System.out.println(object);

}

tx.commit();

} catch (Exception e) {

// 回滚事务

tx.rollback();

e.printStackTrace();

} finally {

// 释放资源

em.close();

}

}

//条件查询

@Test

public void findCondition () {

EntityManager em = null;

EntityTransaction tx = null;

try {

//获取实体管理对象

em = JpaUtils.getEntityManager();

//获取事务对象

tx = em.getTransaction();

tx.begin();

//创建query对象

String jpql = "from Customer where custName like ? ";

Query query = em.createQuery(jpql);

//对占位符赋值,从1开始

query.setParameter(1, "传智%");

//查询并得到返回结果

Object object = query.getSingleResult(); //得到唯一的结果集对象

System.out.println(object);

tx.commit();

} catch (Exception e) {

// 回滚事务

tx.rollback();

e.printStackTrace();

} finally {

// 释放资源

em.close();

}

}

//根据客户id倒序查询所有客户

//查询所有客户

@Test

public void testOrder() {

EntityManager em = null;

EntityTransaction tx = null;

try {

//获取实体管理对象

em = JpaUtils.getEntityManager();

//获取事务对象

tx = em.getTransaction();

tx.begin();

// 创建query对象

String jpql = "from Customer order by custId desc";

Query query = em.createQuery(jpql);

// 查询并得到返回结果

List list = query.getResultList(); // 得到集合返回类型

for (Object object : list) {

System.out.println(object);

}

tx.commit();

} catch (Exception e) {

// 回滚事务

tx.rollback();

e.printStackTrace();

} finally {

// 释放资源

em.close();

}

}

//统计查询

@Test

public void findCount() {

EntityManager em = null;

EntityTransaction tx = null;

try {

//获取实体管理对象

em = JpaUtils.getEntityManager();

//获取事务对象

tx = em.getTransaction();

tx.begin();

// 查询全部客户

// 1.创建query对象

String jpql = "select count(custId) from Customer";

Query query = em.createQuery(jpql);

// 2.查询并得到返回结果

Object count = query.getSingleResult(); // 得到集合返回类型

System.out.println(count); //客户人数

tx.commit();

} catch (Exception e) {

// 回滚事务

tx.rollback();

e.printStackTrace();

} finally {

// 释放资源

em.close();

}

}

}

通过以上等操作,我们就完成了JPA的crud操作。

接下来我们就开始使用spring data jpa来完成crud操作,让我们体会一下什么叫优势。

spring data jpa的crud操作:

首先我们需要引入依赖

<properties>

<spring.version>4.2.4.RELEASE</spring.version>

<hibernate.version>5.0.7.Final</hibernate.version>

<slf4j.version>1.6.6</slf4j.version>

<log4j.version>1.2.12</log4j.version>

<c3p0.version>0.9.1.2</c3p0.version>

<mysql.version>5.1.6</mysql.version>

</properties>

<dependencies>

<!-- junit单元测试 -->

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.9</version>

<scope>test</scope>

</dependency>

<!-- spring beg -->

<dependency>

<groupId>org.aspectj</groupId>

<artifactId>aspectjweaver</artifactId>

<version>1.6.8</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-aop</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context-support</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-orm</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-beans</artifactId>

<version>${spring.version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>${spring.version}</version>

</dependency>

<!-- spring end -->

<!-- hibernate beg -->

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-core</artifactId>

<version>${hibernate.version}</version>

</dependency>

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-entitymanager</artifactId>

<version>${hibernate.version}</version>

</dependency>

<dependency>

<groupId>org.hibernate</groupId>

<artifactId>hibernate-validator</artifactId>

<version>5.2.1.Final</version>

</dependency>

<!-- hibernate end -->

<!-- c3p0 beg -->

<dependency>

<groupId>c3p0</groupId>

<artifactId>c3p0</artifactId>

<version>${c3p0.version}</version>

</dependency>

<!-- c3p0 end -->

<!-- log end -->

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>${log4j.version}</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>${slf4j.version}</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>${slf4j.version}</version>

</dependency>

<!-- log end -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>${mysql.version}</version>

</dependency>

<dependency>

<groupId>org.springframework.data</groupId>

<artifactId>spring-data-jpa</artifactId>

<version>1.9.0.RELEASE</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-test</artifactId>

<version>4.2.4.RELEASE</version>

</dependency>

<!-- el beg 使用spring data jpa 必须引入 -->

<dependency>

<groupId>javax.el</groupId>

<artifactId>javax.el-api</artifactId>

<version>2.2.4</version>

</dependency>

<dependency>

<groupId>org.glassfish.web</groupId>

<artifactId>javax.el</artifactId>

<version>2.2.4</version>

</dependency>

<!-- el end -->

</dependencies>

创建spring配置文件applicationContext.xml,使用spring来管理

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"

xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd

http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd

http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd

http://www.springframework.org/schema/data/jpa

http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

<!-- 1.dataSource 配置数据库连接池-->

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

<property name="driverClass" value="com.mysql.jdbc.Driver" />

<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jpa?characterEncoding=utf-8" />

<property name="user" value="root" />

<property name="password" value="root" />

</bean>

<!-- 2.配置entityManagerFactory -->

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<property name="dataSource" ref="dataSource" />

<property name="packagesToScan" value="com.ithubei.entity" />

<property name="persistenceProvider">

<bean class="org.hibernate.jpa.HibernatePersistenceProvider" />

</property>

<!--JPA的供应商适配器-->

<property name="jpaVendorAdapter">

<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

<property name="generateDdl" value="false" />

<property name="database" value="MYSQL" />

<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />

<property name="showSql" value="true" />

</bean>

</property>

<property name="jpaDialect">

<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />

</property>

</bean>

<!-- 3.事务管理器-->

<!-- JPA事务管理器 -->

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

<property name="entityManagerFactory" ref="entityManagerFactory" />

</bean>

<!-- 整合spring data jpa-->

<jpa:repositories base-package="com.ithubei.dao"

transaction-manager-ref="transactionManager"

entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>

<!-- 4.txAdvice-->

<tx:advice id="txAdvice" transaction-manager="transactionManager">

<tx:attributes>

<tx:method name="save*" propagation="REQUIRED"/>

<tx:method name="insert*" propagation="REQUIRED"/>

<tx:method name="update*" propagation="REQUIRED"/>

<tx:method name="delete*" propagation="REQUIRED"/>

<tx:method name="get*" read-only="true"/>

<tx:method name="find*" read-only="true"/>

<tx:method name="*" propagation="REQUIRED"/>

</tx:attributes>

</tx:advice>

<!-- 5.aop-->

<aop:config>

<aop:pointcut id="pointcut" expression="execution(* com.ithubei.service.*.*(..))" />

<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />

</aop:config>

<context:component-scan base-package="com.ithubei"></context:component-scan>

<!--组装其它 配置文件-->

</beans>

创建和数据库表映射的实体类

package com.ithubei.entity;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.Table;

/**

*

* * 所有的注解都是使用JPA的规范提供的注解,

* * 所以在导入注解包的时候,一定要导入javax.persistence下的

*/

@Entity //声明实体类

@Table(name="cst_customer") //建立实体类和表的映射关系

public class Customer {

@Id//声明当前私有属性为主键

@GeneratedValue(strategy=GenerationType.IDENTITY) //配置主键的生成策略

@Column(name="cust_id") //指定和表中cust_id字段的映射关系

private Long custId;

@Column(name="cust_name") //指定和表中cust_name字段的映射关系

private String custName;

@Column(name="cust_source")//指定和表中cust_source字段的映射关系

private String custSource;

@Column(name="cust_industry")//指定和表中cust_industry字段的映射关系

private String custIndustry;

@Column(name="cust_level")//指定和表中cust_level字段的映射关系

private String custLevel;

@Column(name="cust_address")//指定和表中cust_address字段的映射关系

private String custAddress;

@Column(name="cust_phone")//指定和表中cust_phone字段的映射关系

private String custPhone;

public Long getCustId() {

return custId;

}

public void setCustId(Long custId) {

this.custId = custId;

}

public String getCustName() {

return custName;

}

public void setCustName(String custName) {

this.custName = custName;

}

public String getCustSource() {

return custSource;

}

public void setCustSource(String custSource) {

this.custSource = custSource;

}

public String getCustIndustry() {

return custIndustry;

}

public void setCustIndustry(String custIndustry) {

this.custIndustry = custIndustry;

}

public String getCustLevel() {

return custLevel;

}

public void setCustLevel(String custLevel) {

this.custLevel = custLevel;

}

public String getCustAddress() {

return custAddress;

}

public void setCustAddress(String custAddress) {

this.custAddress = custAddress;

}

public String getCustPhone() {

return custPhone;

}

public void setCustPhone(String custPhone) {

this.custPhone = custPhone;

}

}

创建dao层接口CustomerDao,并继承JpaRepository和JpaSpecificationExecutor接口

/**

* 定义一个dao层接口,此接口只需要继承JpaRepository和JpaSpecificationExecutor接口即可,该接口就具备了增删改 * 查和分页等功能。

* JpaRepository<实体类类型,主键类型>:完成基本的CRUD操作

* JpaSpecificationExecutor<实体类类型>:用于复杂查询(分页等查询操作)

* @author DELL

*

*/

public interface CustomerDao extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer>{

}

dao层编码已经写好了,现在我们就可以来测试CustomerDao来实现crud操作。

package com.ithubei.test;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.ithubei.dao.CustomerDao;

import com.ithubei.entity.Customer;

/**

* 测试:调用CustomerDao接口完成增删改查就等操作

* @author DELL

*

*/

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations="classpath:applicationContext.xml")

public class CustomerDaoTest {

@Autowired

private CustomerDao customerDao;

/**

* 保存操作:调用save()方法

*/

@Test

public void testSave() {

Customer customer = new Customer();

customer.setCustName("黑马程序员");

//保存

customerDao.save(customer);

}

/**

* 修改客户信息:调用save()方法

* 对于save():如果执行此方法时对象中存在id属性,即为更新操作,会根据id查询,再更新

* 如果此方法中不存在id属性,则为保存操作

*/

@Test

public void testUpdate() {

//先根据id查询id为1的客户

Customer customer = customerDao.findOne(96l);

//修改客户名称

customer.setCustName("授课123");

//更新

customerDao.save(customer);

}

/**

* 删除操作

*/

@Test

public void testDelete() {

customerDao.delete(96l);

}

/**

* 根据id查询:调用findOne()

*/

@Test

public void testFindById() {

Customer customer = customerDao.findOne(97l);

System.out.println(customer);

}

}

通过以上测试,我们发现CustomerDao接口下并没有写任何的方法,但是它却具备了crud等操作,只是因为它继承了JpaRepository和JpaSpecificationExecutor两个接口,我们就可以使用这两个接口为我们提供的方法来进行crud等操作。

现在我们就来看一下这两个接口下的方法列表:

在这里插入图片描述

在这里插入图片描述

这两个接口中定义了如此多的方法,方便我们在我们项目中完成基本的操作了。

spring data jpa是一个优势,它减轻了我们的工作量。所以学会它是每个程序员应该做的事情,建议大家都能够去学好它。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

以上是 详谈hibernate,jpa与spring data jpa三者之间的关系 的全部内容, 来源链接: utcz.com/p/250897.html

回到顶部