详谈hibernate,jpa与spring data jpa三者之间的关系
目录
- 前提
- 文字说明
- CRUD操作
前提
其实很多框架都是对另一个框架的封装,我们在学习类似的框架的时候,难免会进入误区,所以我们就应该对其进行总结归纳,对比。本文就是对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是一个优势,它减轻了我们的工作量。所以学会它是每个程序员应该做的事情,建议大家都能够去学好它。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。