谈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,jpa与spring data jpa三者之间的关系_第1张图片
创建hibernate核心配置文件hibernate.cfg.xml




	
		org.hibernate.dialect.MySQLDialect
		com.mysql.jdbc.Driver
		jdbc:mysql:///hibernate
		root
		root

		org.hibernate.connection.C3P0ConnectionProvider
		true
		true
		update

		
		thread
		
		
	

创建实体类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





		
		
			
			
				
				
			
			
			
			
			
			
			
			
			
		

以上我们就完成了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 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 list = qr.list();
		for (Object object : list) {
			System.out.println(object);
		}
		tx.commit();
		session.close();
	}

JPA的crud操作
该操作我们用maven的方式来构建依赖
首先我们需要引入依赖:


		UTF-8
		5.0.7.Final
	

	
		
		
			junit
			junit
			4.12
			test
		

		
		
			org.hibernate
			hibernate-entitymanager
			${project.hibernate.version}
		

		
		
			org.hibernate
			hibernate-c3p0
			${project.hibernate.version}
		

		
		
			log4j
			log4j
			1.2.17
		

		
		
			mysql
			mysql-connector-java
			5.1.6
		
	

在这里插入图片描述
在resources目录下创建META-INF目录,并在该目录下创建persistence.xml文件



	
	
		
		org.hibernate.jpa.HibernatePersistenceProvider
		
			
			
			
			
			
			
			
			

			
			
			
			
			
		
	


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

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操作:
首先我们需要引入依赖


        4.2.4.RELEASE
        5.0.7.Final
        1.6.6
        1.2.12
        0.9.1.2
        5.1.6
    

    
        
        
            junit
            junit
            4.9
            test
        
        
        
        
            org.aspectj
            aspectjweaver
            1.6.8
        

        
            org.springframework
            spring-aop
            ${spring.version}
        

        
            org.springframework
            spring-context
            ${spring.version}
        

        
            org.springframework
            spring-context-support
            ${spring.version}
        

        
            org.springframework
            spring-orm
            ${spring.version}
        

        
            org.springframework
            spring-beans
            ${spring.version}
        

        
            org.springframework
            spring-core
            ${spring.version}
        
        
        

        
        
            org.hibernate
            hibernate-core
            ${hibernate.version}
        
        
            org.hibernate
            hibernate-entitymanager
            ${hibernate.version}
        
        
            org.hibernate
            hibernate-validator
            5.2.1.Final
        
        

        
        
            c3p0
            c3p0
            ${c3p0.version}
        
        

        
        
            log4j
            log4j
            ${log4j.version}
        

        
            org.slf4j
            slf4j-api
            ${slf4j.version}
        

        
            org.slf4j
            slf4j-log4j12
            ${slf4j.version}
        
        

        
        
            mysql
            mysql-connector-java
            ${mysql.version}
        

        
            org.springframework.data
            spring-data-jpa
            1.9.0.RELEASE
        

        
            org.springframework
            spring-test
            4.2.4.RELEASE
        
        
        
          
            javax.el  
            javax.el-api  
            2.2.4  
          
          
          
            org.glassfish.web  
            javax.el  
            2.2.4  
         
        
    

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



	
	
	
		
		
		
		
	
	
	
	
		
		
		
			
		
		
		
			
				
				
				
				
			
		
		
			
		
	
    
	
	
	
	
		
	
	
	
	
		
	
	
		
			
			
			
			
			
			
			
		
	
	
	
	
		
		
	
	
	
		
	
	



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

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, JpaSpecificationExecutor{

}

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等操作。
现在我们就来看一下这两个接口下的方法列表:
谈hibernate,jpa与spring data jpa三者之间的关系_第2张图片
谈hibernate,jpa与spring data jpa三者之间的关系_第3张图片
这两个接口中定义了如此多的方法,方便我们在我们项目中完成基本的操作了。
spring data jpa是一个优势,它减轻了我们的工作量。所以学会它是每个程序员应该做的事情,建议大家都能够去学好它。
感谢大家的欣赏,本文就到此结束了,祝大家能够达成所愿。

你可能感兴趣的:(java,jpa,数据访问操作)