Springboot Jpa的一些些小技巧

10 篇文章 0 订阅
4 篇文章 0 订阅

1.指定引擎

如果不做任何操作,直接写实体类,那hibernate jpa一般不会选择innodb引擎。如果想要指定引擎,需要在resource目录下添加文件hibernate.properties:

hibernate.dialect.storage_engine=innodb

在application.yaml中做如下配置:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: {}
    password: {}
    url: jdbc:mysql://localhost:3306/test
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

2.实体类与lombok

lombok是开发中的常用工具了,但是一个常用注解@Data会在多边关联时和@Entity发生冲突。建议使用jpa的项目只使用@Getter和@Setter两个注解,其他的诸如@Data,@ToString一概不使用

3.指定主键子增

在实体类的自增主键上:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

4.在单元测试时

单元测试的时候如果涉及到数据库数据的变更,jpa会默认开启rollBack,结果就是看起来数据根本没有新增。解决方案是在标注了@Test的测试方法上再加两个注解:
@Transactional // 配置事务
@Rollback(false)
代码如下:

@Test
@Transactional // 配置事务
@Rollback(false)
public void testAdd() {
}

5.关联表的相关注意事项

  1. 一对多代码实现
  2. 多对多介绍与实现

关联表查询时可能出现的问题:事务管理

由于大多数jpa查询都是通过继承JpaRepository<T, Key>实现的,所以findAll方法也基本都是从这个原始实现来。但是这个方法有一个很严重的问题,由于hibernate并不确定本次数据库交互到底是查询还是更新,所以hibernate也为findAll开启了事务管理。也就是说,一次findAll实际上会执行开启事务、执行查询、关闭事务三步。但是我们知道查询是不用事务管理的,所以我们可以通过如下方式关闭,重写父接口的findAll然后把原本的readOnly改掉:

@Transactional(propagation = Propagation.SUPPORTS)
List<T> findAll();

关联表查询时可能出现的问题:kn + 1次查询

一个主表有@ManyToMany或@OneToMany时,本质上hibernate的查询是:

  • s1:查询主表全量resAll(O(1))
  • s2:根据resAll遍历查询关联对象(O(n))
  • s3:loop s2,直到k(k>=1)个关联关系字段查完,最终的查询为(O(kn + 1))

这种查询非常消耗mysql的服务器资源,因为每一个遍历查询都是一个独立的数据库交互,当主数据规模上千时,一次查询/千次交互的查询交互比,什么服务器也扛不住。如果在发上上一节提到的事务管理问题,则可能发生mysql服务器被打爆的风险。
解决方案是写原生native query sql,把多次查询分开,查询结果放在java里,然后再在java里拼装,必须把关联关系引起的笛卡尔积式查询消除。

OS

我真的好讨厌hibernate jpa

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值