Jpa和MyBatis的对比学习总结

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。

JPA是一个Java应用程序接口规范,描述了使用Java标准平台和Java企业版平台的应用中的关系数据的管理。

Spirng Data JPA

什么是JPA?

维基百科:JPA(Java Persistence API,Java持久化API)是一个Java应用程序接口规范,描述了使用Java标准平台(Java SE)和Java企业版平台(Java EE)的应用中的关系数据的管理。

Spring Data JPA 全面解析:JPA (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范。它为 Java 开发人员提供了一种对象/关联映射工具来管理 Java 应用中的关系数据。他的出现主要是为了简化现有的持久化开发工作和整合 ORM 技术,结束现在 Hibernate,TopLink,JDO 等 ORM 框架各自为营的局面。值得注意的是,JPA 是在充分吸收了现有 Hibernate,TopLink,JDO 等ORM框架的基础上发展而来的,具有易于使用,伸缩性强等优点。从目前的开发社区的反应上看,JPA 受到了极大的支持和赞扬,其中就包括了 Spring 与 EJB3.0 的开发团队

JPA所维护的核心是实体(Entity Bean),而它是通过一个持久化上下文(Persistence Context)来使用的。持久化上下文包含了以前3个部分:

  • 对象关系映射(Object Relational Mapping,简称ORM)描述,JPA支持注解或XML两种形式的描述。
  • 实体操作API,内置通用CRUD操作,来完成对象的持久化与查询。
  • 查询语言,约定了面向对象的查询语句JPQL。

简单来说,JPA就是一种接口规范,一种定义了对象关系映射(ORM)以及实体对象的持久化接口标准的规范,并不是一套直接可用的产品(如:Hibernate)。

Jpa具有的优势

  1. 标准化 : JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。

  2. 容器级特性的支持: JPA框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。

  3. 简单方便 : JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。JPA基于非侵入式原则设计,因此可以很容易的和其它框架或者容器集成。

  4. 查询能力: JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。

  5. 高级特性: JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。


可以从一个简单的user的model中了解JPA注解的使用:

简单解释:

  1. @Entity
    该注解用于表明这个类是一个实体类,会为这个类自动生成一张对应的数据表
  2. @Table(name = “table_name”)
    该注解主要用于修改表名,name的值就是修改的数据表的名称
  3. @Id
    该注解用于声明主键,标在哪个属性上面对应的哪个字段就是主键
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
    该注解的strategy属性主要用于设置主键的增长方式,IDENTITY表示主键由数据库自己生成,从1开始单调递增。
  5. @Column(name = “column_name”)
    该注解的name属性用于更改数据表的列名,如果不想用默认的就用这个属性改吧
  6. @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    这个注解得上是本项目得核心了,它声明了实体之间的多对多关系,使两张数据表关联关联起来,一般是通过生成一张映射表来实现这种映射关系。关于上面的cascade属性和fetch属性,有兴趣的读者可以查资料了解。
  7. @JoinTable
    这个注解是配套@ManyToMany使用的,一般在多对多关系的维护端标注,用于生成上面提到的映射表。一般该注解常用三个属性:name属性表示生成的数据表的名称,joinColumns属性表示关系维护端的主键,inverseJoinColumns则表示关系被维护端的主键。关于嵌套在里面的@JoinColumn注解,在这里主要用于配置映射表的外键,一般有两个属性:name用于配置外键在映射表中的名称,referencedColumnName 用于表明外键在原表中的字段名称。
  8. @JsonBackReference
    关于这个注解,建议先去掉试试然后再加上,对比一下效果。它主要可以使标注属性避免被json序列化,进而避免多对多关系的查询中出现死循环的情况。但是加上了这注解后,就不能进行反向查询了(也就是说不能利用权限名查询拥有这个权限的角色了)

model层具体代码如下:

@Entity
@Data
@Table(name = "lab_user")
public class User {

    @Id
    //该注解的strategy属性主要用于设置主键的增长方式,IDENTITY表示主键由数据库自己生成,从1开始单调递增。
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "user_id")
    private Integer userId;

    @Column(name = "user_name")
    private String userName;

    @Column(name = "password")
    private String passWord;

    @Column(name = "role_id")
    /*
    cascade的注解作用是:group对象的增删改关联到user对象
    fetch是读取查询关联,一对多,一的一方,FetchType默认是LAZY, 多的一方FetchType默认是EAGER
    */
    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinTable(
            name = "user_role", //name是表名

            //joinColumns设置的是entity中属性在关系表的映射名称,name是映射表中的字段名
            joinColumns = {@JoinColumn(name = "user_id")},

            //inverseJoinColumns,name是关系实体Role的id在关系表中的名称
            inverseJoinColumns = {@JoinColumn(name = "role_id")}
    )
    private List<Role> roles;
}

在JPA的接口中声明的方法不用我们去实现,只要满足命名规则JpaRepository类会自动帮我们生成相应的sql语句

dao层具体代码:

public interface UserRepository extends JpaRepository<User,Integer> {

    //根据userId查找所有信息
    public List<User> findAllUsersByUserId(int userId);

    //根据用户username查找所有信息
    public List<User> findAllByUserName(String userName);

    //根据用户userId删除用户
    public void deleteByUserName(String userName);

}

最后附上Spring Data JPA需要的依赖:

<!--整合SpringData JPA-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

MyBatis

什么是MyBatis?

Mybatis:Mybatis是一款优秀的持久层框架,他支持自定义SQL、存储过程以及高级映射(ORM框架:Object Relational Mapping,用于实现面对对象编程语言里不同类型系统的数据之间的转换)。Mybatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。Mybatis可以通过简单的XML或注解来配置和映射原始类型、接口和Java POJO(Plain Old Java Objects,普通老式Java对象)为数据库中的记录。

Mybatis的关注点在于:

  • SQL与POJO的映射,或者说查询结果集与POJO的映射
  • 数据的高效存储于读写
  • 可定制化SQL,支持原生SQL

虽然一直都在使用Mybatis作为项目中的orm框架,但是始终没有深入的去了解。Mybatis就是一个ORM框架,是一个半自动的ORM框架,是一个面向查询结果集的ORM框架,一个关注实体与查询结果集之间的映射关系的ORM框架,且支持自定义SQL、存储过程、高级映射。在此基础上存在二次开发的开源产品:Mybatis-Plus,其在Mybatis的基础上进行了增强。

MyBatis具有的优势:

  1. 与JDBC相比,减少了50%以上的代码量。

  2. MyBatis是最简单的持久化框架,小巧并且简单易学。

  3. MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,并可重用。

  4. 提供XML标签,支持编写动态SQL语句。

  5. 提供映射标签,支持对象与数据库的ORM字段关系映射。

MyBatis的缺点:

  1. SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此,对开发人员编写SQL语句的功底有一定要求。

  2. SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

MyBatis框架适用场合:

  1. MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。

  2. 对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。


通过一个简单的SpringBoot整合Mybatis自动注入的例子了解Mybatis的使用:

  1. 首先通过对SpringBoot项目中的application.yaml文件中添加Mybatis的自动注入:

具体实现如下:

#mybatis的配置
mybatis:
  #config-location: classpath:sqlMapConfig.xml   #设置配置文件的位置(可以省略)
  mapper-locations: classpath:mapper/*.xml    #当前mapper下的所有xml都作为映射文件
  configuration:
    map-underscore-to-camel-case: true      #针对于解决 model数据模型编写的驼峰方式 和 数据库的模型编写的下划线方式 的匹配问题
  type-aliases-package: sboot.model         #可以在model中的peron和Person都映射为一个相同的文件

根据mybatis自动配置的源码学习:

mybatis的配置将Mapper包下的PersonMapper是根据MapperFactoryBean来创建代理对象的,并且实例化sqlsessionFactory来创建到sessionTemplate对象对数据库的每一次的操作的开启和关闭等操作进行持久化支持。

而在mybatis自动配置中,我们不需要再创建MapperFactoryBean 和 sqlsessionFactory来对我们自定义PersonMapper进行动态代理,而是根据注解 @MapperScan 来进行自动配置。

@MapperScan("sboot.mapper"): 此注解用于扫描sboot.mapper包下所有文件的Mapper,在主程序中写入此注解可以在Mapper的接口中省略@Mapper注解。

源码中MybatisAutoConfiguration类中明确说到,在MapperScan找不到的情况下,会生成一个一个Scan来扫描根路径下所有带有@Mapper的接口。所以,当拥有@MapperScan注解的时候,上述方法则不会被调用,也就是说@Mapper注解可以省略。

综上所述,可以明确的得知不需要再对每一个具体的Mapper类注入@Mapper注解了,而是在主程序中直接写入@MapperScan(xxx.mapper)即可。

然后Dao层的编写如下:

public interface PersonMapper {

    public Person selectById(int pid);

    public List<Person> selectAll();

    public void insert(Person p);

    public void delete(int pid);
}
  1. 如此简单的编写之后,Mybatis把sql语句集体放在了resources的Mapper的xml配置文件中:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-drWvBGFb-1631842195709)(/textImgs/image-20201228135316873.png)]

具体实现代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="sboot.mapper.PersonMapper">
    <select id="selectById" resultType="Person">
        select * from person t where t.pid = #{pid}
    </select>
    <select id="selectAll" resultType="Person">
        select * from person
    </select>
    <insert id="insert" parameterType="person">
        /*pid自增*/
        <selectKey keyProperty="pid" resultType="int" order="BEFORE">
            select  last_insert_id()
        </selectKey>
        insert into person(pid, pname, addr, gender, birth)values(#{pid},#{pname},#{addr},#{gender},#{birth} )
    </insert>
    <delete id="delete" parameterType="int" >
        delete  from person  where pid = #{pid}
    </delete>
</mapper>

Spring Data JPA 和 MyBatis的对比:

Mybatis优势:

1)SQL语句可以自由控制,更零活,性能更好

2)SQL与代码分离,易与阅读和维护

3)提供XML标签,支持编写动态SQL语句

Mybatis劣势:

1)简单操作还需要编写SQL语句

2)XML有大量的SQL需要维护

3)Mybatis自身的功能有限,但支持Plugin

JPA优势:

1)JPA移植性更好(JPQL)

2)提供很多CRUD方法,开发效率更高

3)对像化程度更高

JPA劣势:

1)由于非常新,JPA 规范可能还需要进过重要发展才会变得很稳定。

2)JPA 是一个规范而不是一个产品。需要提供商提供一个实施,才能获得这些基于标准的 API 的优势。

序号功能项Spring Data JPAMybatis
1启动配置数据库连接+JPA相关配置数据库连接+Mybatis相关配置
2映射关系注解方式实现POJO与数据表之间的映射XML配置结合自动映射(或驼峰映射),实现POJO与SQL之间的映射
3类型转换Convert,多用于如枚举值的存取TypeHandle,多用于枚举类型数据存储
4读写接口内置提供CRUD、分页、排序、 Example等基础接口,可自我拓展默认不提供实现,由使用者实现,但是Mybatis-Plus提供通用mapper、分页
5查询语言提供约定的查询语言JPQL,同时支持原生SQL支持原生SQL,支持动态SQL
6其他1、支持对象模型正向创建数据库模型;2、提供缓存机制;3、提供乐观锁指定1、提供Interceptor,可以拦截SQL进行一定的处理;2、Mybatis-Plus提供代码生成器、支持数据库模型逆向生成对象模型

理论分析:

  • Spring Data JPA与Mybatis的设计原理不一样,前置根据领域设计进行建模,提倡面向对象思想,但是为了提供兼容性,提供自定义查询方法,可接入其他ORM框架;后者根据数据设计进行建模,多数实现为贫血模型。
  • Spring Data JPA:先有对象关系,后有数据表关系;
  • Mybatis:先有数据表关系,后有对象关系。
  • Spring Data JPA(面向对象设计):强调对象,以及对象的特性(如:封装),考虑的是对象的整个生命周期(包括对象的创建、持久化、状态的变更和行为等),对象的持久化只是对象的一种状态,所有操作皆由对象来完成,是对象的行为引发状态的改变,从而引起持久化状态数据的变化。
  • Mybatis(面向关系设计):强调数据的高效存取,开放数据表的操作,并不受实体的限制,可以随意进行表的关联,持久化的数据类似于某个事物的快照,事物状态的变化后引发对于快照的修改,有点直接面向数据库开发的感觉。
  • Spring Data JPA:SQL为动态创建,创建后存在SQL缓存
  • Mybatis:SQL为静态文件。

如果你觉得这篇文章对您有帮助的话,麻烦帮我点个点个赞关注一下吧,创作不易,有你的支持才是我前进的动力~

  • 8
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

听弧丶

你的鼓励将是我最大的前进动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值