相关文章推荐
伤情的创口贴  ·  Bit - 演算法筆記·  1 年前    · 
风度翩翩的丝瓜  ·  Update multiple rows ...·  1 年前    · 
狂野的松树  ·  yacc - y.tab.c: ...·  1 年前    · 

在实体类上面添加这两个注解,

@DynamicInsert :设置为true,表示insert对象的时候,生成动态的insert语句,如果这个字段的值是null就不会加入到insert语句当中.默认true。 这个我没测试过,插入的时候,空值是否生成sql那点效率关系不大

@DynamicUpdate:设置为true,在开始的时候,我也以为这是忽略空值,但我测试的时候,发现我把实体类设置为null,去替换数据库里的数据,结果依然update成功了,最后才看见有人说,这是动态更新,只观察值是否有变动,和null无关,不知道网上哪些小伙伴是怎么成功的。

在service 或者 Repository层,增加一个切面,每次更新的时候,先通过ID查询一次数据库,然后用beanUtil复制非空字段到目标字段,最后用Repository.save(entity),

  1. 线程安全,并发情况下,会出现意外情况,需要在整个方法上加锁,
  2. 每次多一次查询,效率降低

自定义simpleRepository,重写部分save中的代码,取消原来的repository注册,在启动类上重新使用自定义的simpleRepository

优缺点和上面差不多,只是更内层

每次必须多做一次查询,让我这个稍微有点强迫证的人很难受,于是自己就去翻源码,google找解决办法,在反复查看源码后,终于找到了一种解决办法,没人实践过,我自己测试没有问题,在这里做个记录:

jpa的更新,属于合并更新,而每次在合并中,都是由一个 DefaultMergeEventListener 的事件监听器来执行copy的,所以,我自定义一个 DefaultMergeEventListener

* @Auther: by yaoqiang * @Date: 2019-10-22 09:59 * @Description: public class IgnoreNullEventListener extends DefaultMergeEventListener { public static final IgnoreNullEventListener INSTANCE = new IgnoreNullEventListener(); @Override protected void copyValues(EntityPersister persister, Object entity, Object target, SessionImplementor source, Map copyCache) { //源目标 Object[] original = persister.getPropertyValues( entity ); //存储目标 Object[] targets = persister.getPropertyValues(target); Type[] types = persister.getPropertyTypes(); Object[] copied = new Object[original.length]; for ( int i = 0; i < types.length; i++ ) { if ( original[i] == null || original[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY || original[i] == PropertyAccessStrategyBackRefImpl.UNKNOWN copied[i] = targets[i]; } else { copied[i] = types[i].replace( original[i], targets[i], source, target, copyCache ); persister.setPropertyValues( target, copied );

在这里面,我将条件做了一些修改,使空值使用了targets中的值,也就是原值,

下一步使将 这个监听器,注入进去,源码翻了半天,找到了注册中心:网上也查了一些资料,注意,这里要将原来的DefaultMergeEventListener清理掉,要不然会循环调用,调用两次listeners,不管自定义的在前面还是在后面都会失败,前面,空值要么使在第二次直接覆盖,后面,空值第一次覆盖,第二次全是空值,这里,我也躺了坑,跟着源码跑,才看出来。

* @Auther: by yaoqiang * @Date: 2019-10-22 09:57 * @Description: @Configuration public class HibernateListenerConfigurer { @PersistenceUnit private EntityManagerFactory emf; @PostConstruct protected void init() { SessionFactoryImpl sessionFactory = emf.unwrap(SessionFactoryImpl.class); EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class); registry.getEventListenerGroup(EventType.MERGE).clear(); registry.getEventListenerGroup(EventType.MERGE).prependListener(IgnoreNullEventListener.INSTANCE);

通过上面的配置,我测试了一个,发现不会在更新空值了,而非空会得到更新,并且调用次数和线程问题也由框架自己解决

这两天需要用springboot jpa做更新处理,但是惊讶的发现 jpa种并没有忽略空值的配置,而且网上搜了一堆解决方案,大致做下整理1.在实体类上面添加这两个注解,@DynamicInsert :设置为true,表示insert对象的时候,生成动态的insert语句,如果这个字段的值是null就不会加入到insert语句当中.默认true。 这个我没测试过,插入的时候,空值是否生成...
基于ElasticsearchRepository进行简单封装封装用到的2个自定义类repository层service层service实现类使用时注意 封装用到的2个自定义类 public class PageQuery implements Serializable { private static final long serialVersionUID = 7172912761241281958L; * 当前页 private Integer
JPA 字段为null时不 保存 /更新 jpa 实体类中某些字段为null时,执行save操作也会将null 存入,更新时如果将数据查询出再set显得非常的鸡肋,尤其是对于createTime,updateTime这一类记录数据更没必要再次查询。 @Column(insertable = false,updatable = false)即可在save时忽略此字段,这样 jpa 更新插入时就不会去更新这个字段了,而是完全由数据库维护。columnDefinition和后面的设置,就等于在数据库中设置DEFAULT C
今天在开发上碰到一个 问题 ,在做页面展示的时候传给前端十个字段,前端修改了其中3个的 ,所以只传了3个 给后端,其余字段默认为null,更新后其他7个字段在全部变为了 。 在前端没法全量回传所有属性的前提下,由后端来处理这类 问题 。 解决方法:1.写一个工具方法(UpdateUtil) 用来筛选出所有的 字段 2.更新时先通过id搜索原始对象,通过findone()等都可以 3.将前端传来的不为 ...
Spring Data JPA 可以理解为对 JPA 规范的再次封装抽象,默认的底层还是使用了Hibernate的 JPA 技术实现,使用JPQL(Java Persistence Query Language)作为查询语言, 可以通过@Query注解来实现。JPQL是面向对象的查询语言,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。下面是一个查询的例子: @Query(value = “select name,author,price from Book b where b.pric
最近在学习 SpringBoot ,在调用 Jpa Repository接口的save方法时报错,如下: 一直在想调用人家封装的方法怎么还会报错,经过查询原来是主键自增策略的 问题 。我的代码:@Entity public class ProductCategory { /*类目id*/ @GeneratedValue private Integer category...
Spring Boot是Spring框架中的一部分,它极大地简化了Spring的开发流程。使用Spring Boot可以非常容易地构建API,Web应用程序以及各种服务。Spring Boot提供了许多自动化配置和默认 ,这使得开发人员可以专注于编写业务代码而不是配置框架。而Spring Boot JPA 是Spring Boot中的一个模块,它提供了一个Java持久层API,可用于管理和操作Java对象到关系数据的映射。它是一种非常高效和灵活的ORM框架。 它不仅使查询和持久化数据变得轻松,而且相比于原始的JDBC方法而言具有更高的性能。 Spring Boot JPA 的文档是非常详细和易于理解的。它解释了如何配置和使用 JPA 的所有方面,以及如何处理各种常见 问题 。随着阅读的深入,文档将逐渐介绍 JPA 的高级概念,例如事务管理,查询优化,复杂关系映射等。 Spring Boot JPA 文档的其中一个主要优点是众多的示例代码。代码覆盖了许多常见的用例,从简单的查询和持久化对象到复杂查询和处理一对多及多对多关系。这些示例代码非常清晰,易于理解,并向开发人员展示了如何在Spring Boot应用程序中使用 JPA 。 综上所述,Spring Boot JPA 文档提供了一种无与伦比的方式来学习和使用 JPA 。 它提供了全面的指南,带有丰富的示例代码,让开发人员更加轻松地掌握Spring Boot JPA