spring data jpa DynamicUpdate 不起作用的问题解决

参考:https://blog.csdn.net/xiao_xuwen/article/details/53579353

及参考了很多。貌似目前大部分都是先去数据库查一下,然后把不为null的值对应的覆盖下,然后保存。

没找到其他更好的办法,但是为了稍微写的优雅点,调用的方便点,修改如下:

自己定义了repository类,覆盖重写了默认的save方法。另外判断加了是否有dynamicupdate注解,根据是否有注解,来对应的处理 属性null值更新情况。实际就是dynamicupdate的效果

/**
 * @author zhengk
 * @description
 * @since 2018-8-19 0:00
 */
public   class BaseRepositoryImpl extends QuerydslJpaRepository
        implements BaseRepository {

    private final JpaEntityInformation entityInformation;

    private final EntityManager em;

    @Autowired
    public BaseRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityInformation = entityInformation;
        this.em = entityManager;
    }


    /**
     * save方法,保存或新增
     */
    @Override
    @Transactional
    public  S save(S entity) {
        if (entityInformation.isNew(entity)) {
            em.persist(entity);
            return entity;
        } else {
            DynamicUpdate dynamicUpdateValue= entity.getClass().getAnnotation(org.hibernate.annotations.DynamicUpdate.class);

            //如果有动态更新的注解,并且值是true,那么动态更新
            if(dynamicUpdateValue!=null&&dynamicUpdateValue.value()){
                //获取ID
                ID entityId = (ID) entityInformation.getId(entity);
                //查询数据库数据
                T dataFromDb = findById(entityId).get();
                //获取为空的属性-覆盖的时候忽略
                String[] ignoreProperties = getNotNullProperties(entity);
                //用数据库对象对应的信息覆盖实体中属性为null的信息
                BeanUtils.copyProperties(dataFromDb, entity, ignoreProperties);
            }
            //更新
            return em.merge(entity);
        }
    }

    /**
     * 获取对象的不为null的属性
     */
    private static String[] getNotNullProperties(Object src) {
        //1.获取Bean
        BeanWrapper srcBean = new BeanWrapperImpl(src);
        //2.获取Bean的属性描述
        PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();
        //3.获取Bean的空属性
        Set properties = new HashSet<>();
        for (PropertyDescriptor propertyDescriptor : pds) {
            String propertyName = propertyDescriptor.getName();
            Object propertyValue = srcBean.getPropertyValue(propertyName);
            if (propertyValue!=null) {
                properties.add(propertyName);
            }
        }
        return properties.toArray(new String[0]);
    }

}

 

/**
 * @author zhengk
 * @description
 * @since 2018-8-19 8:17
 */
public class BaseRepositoryFactoryBean, T,
        ID extends Serializable > extends JpaRepositoryFactoryBean {
    /**
     * Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface.
     *

     * @param repositoryInterface must not be {@literal null}
    .
     */
    public BaseRepositoryFactoryBean(Class < ? extends R >
                                             repositoryInterface) {
        super(repositoryInterface);
    }

    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
        return new BaseRepositoryFactory(em);
    }

    //创建一个内部类,该类不用在外部访问
    private static class BaseRepositoryFactory
            extends JpaRepositoryFactory {

        private final EntityManager em;

        public BaseRepositoryFactory(EntityManager em) {
            super(em);
            this.em = em;
        }

        //设置具体的实现类是BaseRepositoryImpl
        @Override
        protected BaseRepositoryImpl getTargetRepository(RepositoryInformation information) {
            JpaEntityInformation entityInformation = getEntityInformation(information.getDomainType());

            return getTargetRepositoryViaReflection(information, entityInformation, em);
        }

        //设置具体的实现类的class
        @Override
        protected Class getRepositoryBaseClass(RepositoryMetadata metadata) {
            return BaseRepositoryImpl.class;
        }
    }
}

 

@EnableJpaRepositories (repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class)//指定自己的工厂类
@SpringBootApplication
public class NbzlcyApplication {

   public static void main(String[] args) {
      SpringApplication.run(NbzlcyApplication.class, args);
   }
}
/**
 * 自定义基础的仓库类,通过改变集成的仓库不一样,来控制提供的接口
 * zhengk
 * @param 
 * @param 
 */
@NoRepositoryBean
public interface BaseRepository extends JpaRepository,QuerydslPredicateExecutor {

}

初步代码是这样的,看后面找到合适的再修改吧

你可能感兴趣的:(spring,boot,spring,data,jpa)