Spring data 系列之spring data jpa
背景:随着互联网技术的发展,现在的企业开发中用到的用于数据存储的产品,不再仅仅是关系型数据库,而是要根据场景需要选择不同的存储技术,比如用于缓存热点数据的redis,用于存储文档数据的mongodb,用于支持强大搜索功能的elasticsearch等等。
在Java中,对于上面所说的产品都提供了优秀的访问技术。比如针对关系型数据库的mybatis、jpa等技术,针对于redis的jedis技术等等..... 这些技术虽然可以很好的针对各个存储产品进行访问操作,但同时也带来了新的问题,那就是不同的持久层技术的API是不一样的。这样一来,开发人员就必须同时掌握多种数据访问技术,这无疑增加了开发成本。有没有这样一种技术,它可以使用一套API支持各个不同的存储的访问呢?就在这样的需求下,SpringData产生了。
在互联网企业中,早期因为要抢占市场等因素,因而需要先推出产品,导致前期业务不确定性很高,因此操作数据库层的框架就需要灵活,绝大部分项目采用的框架就是mybatis,也一直延续至今。而在传统软件企业中,业务的变化没有那么大,比如人力资源管理系统,ERP系统,又或者金融业的大部分系统,更适合领域设计模式,也有必要考虑更适合操作数据库的框架。
本节主要讲述数据库层。现在企业中对数据库操作使用的框架主流的有MyBatis,hibernate,spring data jpa。这三个框架因为设计的时候出发点不同,因此我们有必要了解哪些业务场景使用哪种框架更合适。
Hibernate:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装。属于全自动的ORM框架,着力点在于POJO和数据库表之间的映射,完成映射即可自动生成和执行sql。
Mybatis:MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。属于半自动的ORM框架,着力点在于POJO和SQL之间的映射,自己编写sql语句,然后通过配置文件将所需的参数和返回的字段映射到POJO。
Spring Data JPA:Spring Data是一个通过命名规范简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框架和云计算数据服务。Spring data jpa使用jpa规范,支持这套规范的框架是hibernate,因此底层框架还是hibernate。
实现上:mybatis只有一个核心jar包,另外和spring整合需要mybatis-spring的jar包,使用缓存需要mybatis-ehcache的jar包,而hibernate需要一系列的jar包,这也侧面反映了mybatis相对小巧,简单,而hibernate相对来说比较强大,复杂;mybatis的配置主要包括一个用于映射各种类的xml文件以及和实体类一一对应的映射文件,hibernate包括hibernate.cfg.xml和实体类的配置文件hibernate.hbm.xml。
Hibernate的开发难度要大于Mybatis、Spring Data。主要是由于Hibernate封装了完整的对象关系映射机制,以至于内部的实现比较复杂、庞大,学习周期较长。
Mybatis 主要依赖于SQL的编写与ResultMap的映射。
Spring Data易上手,通过命名规范、注解查询简化查询操作。
简单查询:
Hibernate 提供了基础的查询方法,也可以根据具体的业务编写相应的SQL;
Mybatis需要手动编写SQL语句;
Spring Data 继承基础接口,可使用内置的增删改查方法。
从上述几点差别不难得出,针对sql底子不够,而单表操作占据主导的项目建设时,优先考虑spring data jpa。
Spring Data 简介
1.什么是Spring Data
Spring Data是一个用来简化dao层开发的框架。它在保证了各个底层存储特性的同时,提供了一套统一的数据访问API。它可以很好的支持常用的关系型数据库和非关系型数据库。使用Spring Data作为dao层开发技术,将大大简化代码量,而且其API比各个技术的原生API更加简单易用。
2.Spring Data的主要模块
Spring Data支持的持久层技术非常多,只介绍几个常见的:
Spring Data common Spring Data 的核心模块,定义了Spring Data的核心功能
Spring Data JDBC 对JDBC的Spring Data存储库支持
Spring Data JPA 对JPA的Spring Data存储库支持
Spring Data MongoDB 对MongoDB的基于Spring对象文档的存储库支持
Spring Data Redis 封装Jedis技术,对redis实现访问操作
Spring Data Elasticsearch 对Elasticsearch实现访问操作
JPA回顾
JPA全称是Java Persistence API,即java持久化api,是一套ORM规范,不是ORM框架,JPA并没有提供ORM实现,只是提供了一些编程的接口。如下图所示:
JDBC |
数据库 |
其它ORM框架 |
Hibernate |
JPA |
JPA实战
搭建JPA环境,并实现一条数据的增删查改。
准备数据库
CREATE TABLE `student` (
`SId` varchar(10) COLLATE utf8_bin DEFAULT NULL,
`Sname` varchar(10) COLLATE utf8_bin DEFAULT NULL,
`Sage` datetime DEFAULT NULL,
`Ssex` varchar(10) COLLATE utf8_bin DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
创建java工程,导入坐标
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.49version>
dependency>
<dependency>
<groupId>org.hibernategroupId>
<artifactId>hibernate-entitymanagerartifactId>
<version>5.0.7.Finalversion>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.12version>
dependency>
dependencies>
创建实体类
public class Student implements Serializable { private String Sid; private String Sname; private String Ssex; private Date Sage;
//省略get和set以及toString方法
}
在实体类中配置映射关系
@Entity
@Table(name = "student")
public class Student implements Serializable {
@Id
@Column(name = "SId")
private String Sid;
@Column(name = "Sname")
private String Sname;
@Column(name = "Ssex")
private String Ssex;
@Column(name = "Sage")
private Date Sage;
}
加入jpa配置文件
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"> <persistence-unit name="jpa01" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.jpa.HibernatePersistenceProviderprovider> <class>com.test.Studentclass> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql:///practice"/> <property name="javax.persistence.jdbc.user" value="root"/> <property name="javax.persistence.jdbc.password" value="root"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true"/> <property name="hibernate.hbm2ddl.auto" value="update"/> properties> persistence-unit> persistence>
测试
public class TestJpa { @Test public void testSave(){ //1 创建持久化管理器工厂 String persistenceUnitName = "jpa01"; EntityManagerFactory factory = Persistence.createEntityManagerFactory(persistenceUnitName); //2 创建持久化管理器 EntityManager entityManager = factory.createEntityManager(); //3 获取事务 EntityTransaction transaction = entityManager.getTransaction(); transaction.begin(); //4 操作 Student stu = new Student(); stu.setSid("31"); stu.setSage(new Date()); stu.setSname("zhang san "); stu.setSsex("man"); entityManager.persist(stu); //5 事务提交 transaction.commit(); //6 关闭资源 entityManager.close(); } }
结果是正常保存到表,修改,查询和删除跟插入整体差别不大,只要在上面的操作修改即可。例如:
@Test
public void testFindBySid() {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa01");
EntityManager entityManager = factory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
Student stu = entityManager.find(Student.class,"31");
System.out.println(stu);
transaction.commit();
entityManager.close();
}
大体回顾了一边jpa操作数据库,下面介绍它的两个重要API,一个是EntityManagerFactory,另一个是EntityManager:
EntityManagerFactory接口主要用来创建EntityManager实例。
EntityManagerFactory是一个线程安全的对象,并且其创建极其浪费资源,所以编程的时候要保持它是单例的。
在JPA规范中, EntityManager是操作数据库的重要API,他是线程不安全的,需要保持线程独有。重要方法说明:
getTransaction: 获取事务对象
persist:保存操作
merge:更新操作
remove:删除操作
find/getReference:根据id查询