参考: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<T, ID extends Serializable> extends QuerydslJpaRepository<T,ID>
implements BaseRepository<T,ID> {
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 extends T> 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<String> 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<R extends JpaRepository<T, ID >, T,
ID extends Serializable > extends JpaRepositoryFactoryBean<R, T, ID> {
/**
* 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<T, ID extends Serializable>
extends JpaRepositoryFactory {
private final EntityManager em;
public BaseRepositoryFactory(EntityManager em) {
super(em);
this.em = em;
}
//设置具体的实现类是BaseRepositoryImpl
@Override
protected BaseRepositoryImpl<T, ID> 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 <T>
* @param <ID>
*/
@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T,ID>,QuerydslPredicateExecutor<T> {
}
初步代码是这样的,看后面找到合适的再修改吧