iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Mybatis与Jpa的区别和性能对比总结
  • 658
分享到

Mybatis与Jpa的区别和性能对比总结

2024-04-02 19:04:59 658人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

前言 这几天听朋友说JPA很好用,根本不用写sql。我在想一个程序员不写sql还能叫程序员?而且越高级的工具封装越多的工具,可拓展性和效率就非常的低,况且我本身非常不喜欢过于封装的

前言

这几天听朋友说JPA很好用,根本不用写sql。我在想一个程序员不写sql还能叫程序员?而且越高级的工具封装越多的工具,可拓展性和效率就非常的低,况且我本身非常不喜欢过于封装的东西,平时喜欢手写sql,所以一直都是用mybatis去写业务。然后发现jpa的saveAll()批量插入批量更新速度太慢了,导致一些用excel导入的一些东西非常慢,弄得原本同步可以解决的事情每次导入都要开启一个异步,个人感觉这种做法非常不好。因为异步其实就是对当前的业务不影响去另外的时间段去做,例如跑定时任务,异步更新增量信息等。代码里非常多异步包异步的东西,也就是说excel导入是异步,然后jpa又慢,异步里面又包涵异步,整个链路非常长,可能发生问题都要排查半天。

安装jpa和mybatis


<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
	<groupId>Mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

这些东西只要引入一个SpringBoot的xml作为父类就行

创建一个类


@Data
public class TestMybatis {
    private Long id;
    
    private String userId;
    
    private String mainMetric;
    
    private String subMetric;
    
    private String metricItem;
}
@SuppressWarnings("serial")
@javax.persistence.Entity
@javax.persistence.Table(name = "test")
@lombok.Data
public class TestJpa {
    @javax.persistence.Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String userId;
    
    private String mainMetric;
    
    private String subMetric;
    
    private String metricItem;
}

@Repository
public interface TestRee extends JpaRepository<TestRe, String> {

}

这是mybatis的xml


<insert id="insertList">
    insert into test(user_id,main_metric, sub_metric, metric_item) values
    <foreach collection="param" item="item" separator=",">
            (#{item.userId}, #{item.mainMetric}, #{item.subMetric}, #{item.metricItem})
    </foreach>
</insert>

下面我们来看看速度


@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ColaDemoApplication.class})
class ColaDemoApplicationTests {
    @Autowired
    private TestRee testRee;
    @Autowired
    private MetricMapper metricMapper;

    @Test
    void contextLoads() {
        List<TestJpa> jpaList = new ArrayList<>(1000);
        List<com.kakki.colademo.gatewayimpl.database.dataobject.TestMybatis> mybatisList = new ArrayList<>(1000);
        for (int i = 0; i < 1000; i++) {
            TestJpa testJpa = new TestJpa();
            testJpa.setMainMetric(String.fORMat("mainMetric%d", i));
            testJpa.setSubMetric(String.format("subMetric%d", i));
            testJpa.setUserId(String.format("userId%d", i));
            testJpa.setMetricItem(String.format("metricItem%d", i));
            jpaList.add(testRe);
            com.kakki.colademo.gatewayimpl.database.dataobject.TestMybatis testMybatis = new com.kakki.colademo.gatewayimpl.database.dataobject.TestMybatis();
            testMybatis.setMainMetric(String.format("mainMetric%d", i));
            testMybatis.setSubMetric(String.format("subMetric%d", i));
            testMybatis.setUserId(String.format("userId%d", i));
            testMybatis.setMetricItem(String.format("metricItem%d", i));
            mybatisList.add(testR);
        }
        StopWatch jpa = new StopWatch();
        jpa.start();
        testRee.saveAll(jpaList);
        jpa.stop();
        log.info("[jpa]{}ms", jpa.getTotalTimeMillis());

        StopWatch m = new StopWatch();
        m.start();
        metricMapper.insertList(mybatisList);
        m.stop();
        log.info("[m]{}ms", m.getTotalTimeMillis());

    }

}

22:35:10.708 [main] INFO  c.e.c.ColaDemoApplicationTests - [jpa]10576ms
22:35:31.366 [main] INFO  c.e.c.ColaDemoApplicationTests - [m]138ms

可以说相差差不多10倍了吧?这仅仅只是1000条数据。让我们试试10000条

22:36:48.505 [main] INFO  c.e.c.ColaDemoApplicationTests - [jpa]8081ms
22:37:05.005 [main] INFO  c.e.c.ColaDemoApplicationTests - [m]613ms
# 再试试10w条
22:38:49.085 [main] INFO  c.e.c.ColaDemoApplicationTests - [jpa]65710ms
22:39:09.844 [main] INFO  c.e.c.ColaDemoApplicationTests - [m]9448ms

那么这样能看出来很大的差距了吧?为什么会差距这么大呢?我们看看saveAll()源码


    @Transactional
	@Override
	public <S extends T> List<S> saveAll(Iterable<S> entities) {

		Assert.notNull(entities, "Entities must not be null!");

		List<S> result = new ArrayList<S>();

		for (S entity : entities) {
			result.add(save(entity));
		}

		return result;
	}
    @Transactional
	@Override
	public <S extends T> S save(S entity) {

		if (entityInformation.isNew(entity)) {
			em.persist(entity);
			return entity;
		} else {
			return em.merge(entity);
		}
	}

从上面可以看出来是一条条save进去的并且save里面还会去判断这个主键是否为空也就是说n条循环n条if判断,那样性能肯定是衰减得非常多的拉

结论

我在网上看到加入以下这些参数可以变成批量的,但是笔者试过根本没用,可能想要解决这个问题,需要重写他的saveAll()方法然后分片去插入或者更新这样性能会好很多。


spring.jpa.properties.hibernate.jdbc.batch_size=10000
spring.jpa.properties.hibernate.jdbc.batch_versioned_data=true
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true

当然今天我仅仅是用jpa的性能跟mybatis比较,但是作为一个码农深知,技术是为业务服务的。Jpa当然也有他的好处,例如创建一些方法findAllByIdIn(List ids)就可以直接获取到以这个条件查询的列表,还有findAllByOrderIdAndOrderType(String orderId, String orderType)这种一样也可以,可以说非常的方便,也不需要再去写sql,他会全自动的完成你的查询操作。

小结

开发一个小型项目,Jpa效率肯定是比Mybatis高的,但是因为业务需求迭代更新越来越快,Jpa明显是满足不了很多东西,而且维护起来看Sql也是比MyBatis难。所以我更偏向于Mybatis,写的Sql也更加简洁更容易维护。

到此这篇关于Mybatis与Jpa的区别和性能对比的文章就介绍到这了,更多相关Mybatis与Jpa区别和性能内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Mybatis与Jpa的区别和性能对比总结

本文链接: http://www.lsjlt.com/news/128894.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作