前言
SpringDataJpa和Mybatis一样,在三层架构中处于持久层,就是专门与数据库打交道的,那我用Mybatis用得好好的为什么要再学SpringDataJpa?这就要从定义说起。
1. JPA
JPA,全称是Java Persistence Api,Java持久化接口,它不是一种技术,而是一种规范。作为规范,它将Java对象的创建过程和具体的创建形式解耦。我们的程序中并不会把所有的Java对象都进行持久化,只会保留关键业务对象,JPA规范就是允许我们自定义应该保留哪些对象,以及如何在Java应用程序中保留这些对象。
2. Hibernate
Hibernate是我在大学的时候也是学的第一门持久化层框架,它就是遵循了JPA规范的框架,也有文章说Hibernate是JPA的前身,简单来说Hibernate是一款重量级的持久化层框架,学习成本较高、全自动化是它的特点,同时这些特点也决定了它不适合做互联网项目。
3. Mybatis
Mybatis和Hibernate的作用相同,都是与数据库做交互,但定位不同,Mybatis的轻量和它的SQL自定义让它成为互联网项目持久化层框架的首选,当然SQL需要开发人员书写(即使是注解模式)的特点让它在传统项目的面前不如遵循JPA的Hibernate,所以说技术没有高低之分,只有落脚点不同之别。
4. SpringDataJpa
说了那么多那SpringDataJpa究竟是什么?我的理解是,它还是对JPA的进一步封装,地位处于JPA与实际落地技术(如Hibernate)之间,所以SpringDataJpa仍然不是“干活的技术”,Hibernate才是干活的工人,SpringDataJpa是做指派工作的包工头。原因在于基于SpringDataJpa,还可以再具体指定使用哪个持久层框架来与数据库做交互。另外我认为,在Spring大行天下的当今,在项目技术选型时选用SpringDataJpa可以和Spring有更好的交融,这是个潜藏的优势。具体可以看配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<!--对Spring和SpringDataJpa进行配置-->
<!--1.数据源-->
<context:property-placeholder location="classpath*:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--2.配置Jpa中一个非常重要的对象——entityManagerFactory
它相当于MyBatis中的SqlSessionFactory,就是一些框架的细节配置-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!--配置数据源-->
<property name="dataSource" ref="dataSource"/>
<!--配置包扫描:packagesToScan
,就是框架要帮我们生成sql,那要帮哪些pojo对应的数据表生成呢?就指定pojo包路径,告诉框架去生成可以操作这个包下的pojo类的sql-->
<property name="packagesToScan" value="cn.lamb.pojo"/>
<!--指定jpa的具体实现:persistenceProvider(持久化提供者)
,jpa是一种规范,并不直接操作持久层,它的具体实现要靠遵循jap规范的持久化层框架,这里使用的是Hibernate,所以将它指定为jpa的具体实现-->
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
</property>
<!--指定jpa的方言
,不同框架对sql的处理是不同的,每种框架都有自己的一套“规则”,所以要指定方言,这里要和persistenceProvider一致-->
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
</property>
<!--===================既然使用的是Hibernate框架做具体实现,那么也要对hibernate做具体配置========================-->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!--需不需要在每次程序启动时创建不存在的数据表
,这个不需要我们操心-->
<property name="generateDdl" value="false"/>
<!--现在Hibernate要处理什么数据库-->
<property name="database" value="MYSQL"/>
<!--要和现在使用的数据库有照应
,数据库之间的语法或多或少有差异,因此要根据database设置方言-->
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
<!--是否显示SQL
,操作数据库时是否打印SQL-->
<property name="showSql" value="true"/>
</bean>
</property>
</bean>
<!--3.使用上面的entityManagerFactory
<jpa:repositories>配置jpa的Dao层细节
base-package指定Dao层 -->
<jpa:repositories base-package="cn.lamb.dao" entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="jpaTransactionManager"/>
<!--4.事务处理器
,Mybatis、jdbcTemplate使用的事务管理器是org.springframework.jdbc.datasource.DataSourceTransactionManager
jpa使用的事务管理器是org.springframework.orm.jpa.JpaTransactionManager-->
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!--5.开启Spring包扫描-->
<context:component-scan base-package="cn.lamb"/>
</beans>
复制代码
多说两句
谈起操作数据库,大致可以分为两个阶段:
- JDBC 阶段:初学 JDBC 会使用原生的 JDBC 的 API,通过写死代码做数据库交互。
- 会使用数据库连接池:比如:c3p0、dbcp、druid,甚至一些第三方工具,比如 dbutils 。
我认为万变不离其宗的还是 JDBC——它贯穿始终,即使到了框架部分,也会对 JDBC 进行整合,所以什么时候回归朴素吧,把JDBC的源码捡一捡。