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

网友投稿 1324 2023-01-06

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

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

前言

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

安装jpa和mybatis

org.mybatis.spring.boot

mybatis-spring-boot-starter

mysql

mysql-connector-java

org.springframework.boot

spring-boot-starter-data-jpa

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

创建一个类

@Data

public class TestMybatis {

pKEEIpbUburivate 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;

}

/**

* @author Kakki

* @version 1.0

* @create 2021-06-17 17:39

* 这个是用来Jpa跟Mapper差不多

*/

@Repository

public interface TestRee extends JpaRepository {

}

这是mybatis的xml

insert into test(user_id,main_metric, sub_metric, metric_item) values

(#{item.userId}, #{item.mainMetric}, #{item.subMetric}, #{item.metricItem})

下面我们来看看速度

@Slf4j

@RunWith(SpringRunner.class)

@SpringBootTest(classes = {ColaDemoApplication.class})

class ColaDemoApplicationTests {

@Autowired

private TestRee testRee;

@Autowired

private MetricMapper metricMapper;

@Test

void contextLoads() {

List jpaList = new ArrayList<>(1000);

List 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]10576msKEEIpbUbu

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 List saveAll(Iterable entities) {

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

List result = new ArrayList();

for (S entity : entities) {

result.add(save(entity));

}

return result;

}

@Transactional

@Override

public 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也更加简洁更容易维护。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:知识服务app运营模式(知识付费app的商业模式)
下一篇:小程序生态游戏策划书(小程序游戏框架)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~