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.关联表的相关注意事项
关联表查询时可能出现的问题:事务管理
由于大多数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
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/153512.html