java 重写 tensorflow_扩展JPA方法,重写save方法

为什么要重构save?

jpa提供的save方法会将原有数据置为null,而大多数情况下我们只希望跟新自己传入的参数,所以便有了重写或者新增一个save方法。

本着解决这个问题,网上搜了很多解决方案,但是没有找到合适的,于是自己研究源码,先展示几个重要源码

1、SimpleJpaRepository方法实现类,由于代码过多只展示部分源码

public class SimpleJpaRepository implements JpaRepository, JpaSpecificationExecutor {

private static final String ID_MUST_NOT_BE_NULL = "The given id must not be null!";

private final JpaEntityInformation entityInformation;

private final EntityManager em;

private final PersistenceProvider provider;

@Nullable

private CrudMethodMetadata metadata;

public SimpleJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager) {

Assert.notNull(entityInformation, "JpaEntityInformation must not be null!");

Assert.notNull(entityManager, "EntityManager must not be null!");

this.entityInformation = entityInformation;

this.em = entityManager;

this.provider = PersistenceProvider.fromEntityManager(entityManager);

}

public SimpleJpaRepository(Class domainClass, EntityManager em) {

this(JpaEntityInformationSupport.getEntityInformation(domainClass, em), em);

}

public void setRepositoryMethodMetadata(CrudMethodMetadata crudMethodMetadata) {

this.metadata = crudMethodMetadata;

}

@Nullable

protected CrudMethodMetadata getRepositoryMethodMetadata() {

return this.metadata;

}

protected Class getDomainClass() {

return this.entityInformation.getJavaType();

}

private String getDeleteAllQueryString() {

return QueryUtils.getQueryString("delete from %s x", this.entityInformation.getEntityName());

}

@Transactional

public S save(S entity) {

if (this.entityInformation.isNew(entity)) {

this.em.persist(entity);

return entity;

} else {

return this.em.merge(entity);

}

}

}

2、JpaRepositoryFactoryBean

public class JpaRepositoryFactoryBean, S, ID> extends TransactionalRepositoryFactoryBeanSupport {

@Nullable

private EntityManager entityManager;

public JpaRepositoryFactoryBean(Class extends T> repositoryInterface) {

super(repositoryInterface);

}

@PersistenceContext

public void setEntityManager(EntityManager entityManager) {

this.entityManager = entityManager;

}

public void setMappingContext(MappingContext, ?> mappingContext) {

super.setMappingContext(mappingContext);

}

protected RepositoryFactorySupport doCreateRepositoryFactory() {

Assert.state(this.entityManager != null, "EntityManager must not be null!");

return this.createRepositoryFactory(this.entityManager);

}

protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {

return new JpaRepositoryFactory(entityManager);

}

public void afterPropertiesSet() {

Assert.state(this.entityManager != null, "EntityManager must not be null!");

super.afterPropertiesSet();

}

}

根据源码及网上资料总结如下方案

一、重写save

优势:侵入性小,缺点将原方法覆盖。

创建JpaRepositoryReBuild方法继承SimpleJpaRepository。直接上代码

public class JpaRepositoryReBuild extends SimpleJpaRepository {

private final JpaEntityInformation entityInformation;

private final EntityManager em;

@Autowired

public JpaRepositoryReBuild(JpaEntityInformation entityInformation, EntityManager entityManager) {

super(entityInformation, entityManager);

this.entityInformation = entityInformation;

this.em = entityManager;

}

/**

* 通用save方法 :新增/选择性更新

*/

@Override

@Transactional

public S save(S entity) {

//获取ID

ID entityId = (ID) this.entityInformation.getId(entity);

T managedEntity;

T mergedEntity;

if(entityId == null){

em.persist(entity);

mergedEntity = entity;

}else{

managedEntity = this.findById(entityId).get();

if (managedEntity == null) {

em.persist(entity);

mergedEntity = entity;

} else {

BeanUtils.copyProperties(entity, managedEntity, getNullProperties(entity));

em.merge(managedEntity);

mergedEntity = managedEntity;

}

}

return entity;

}

/**

* 获取对象的空属性

*/

private static String[] getNullProperties(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 (StringUtils.isEmpty(propertyValue)) {

srcBean.setPropertyValue(propertyName, null);

properties.add(propertyName);

}

}

return properties.toArray(new String[0]);

}

}

启动类加上JpaRepositoryReBuild 方法

@EnableJpaRepositories(value = "com.XXX", repositoryBaseClass = JpaRepositoryReBuild.class)

@SpringBootApplication

@EnableDiscoveryClient // 即消费也注册

public class SystemApplication {

public static void main(String[] args) {

SpringApplication.run(SystemApplication.class, args);

}

}

二、扩张jpa方法

1、新建新增方法接口BaseRepository

@NoRepositoryBean

public interface BaseRepository extends JpaRepository {

/**

* 保存但不覆盖原有数据

* @param entity

* @return

*/

T saveNotNull(T entity);

}

2、创建BaseRepositoryImpl方法

@NoRepositoryBean

public class BaseRepositoryImpl extends SimpleJpaRepository implements BaseRepository {

private final JpaEntityInformation entityInformation;

private final EntityManager em;

public BaseRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {

super(entityInformation,entityManager);

this.entityInformation = entityInformation;

this.em = entityManager;

}

public BaseRepositoryImpl(Class domainClass, EntityManager em) {

this(JpaEntityInformationSupport.getEntityInformation(domainClass, em), em);

}

@Override

@Transactional

public T saveNotNull(T entity) {

//获取ID

ID entityId = (ID) this.entityInformation.getId(entity);

T managedEntity;

T mergedEntity;

if(entityId == null){

em.persist(entity);

mergedEntity = entity;

}else{

managedEntity = this.findById(entityId).get();

if (managedEntity == null) {

em.persist(entity);

mergedEntity = entity;

} else {

BeanUtils.copyProperties(entity, managedEntity, getNullProperties(entity));

em.merge(managedEntity);

mergedEntity = managedEntity;

}

}

return mergedEntity;

}

private static String[] getNullProperties(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 (StringUtils.isEmpty(propertyValue)) {

srcBean.setPropertyValue(propertyName, null);

properties.add(propertyName);

}

}

return properties.toArray(new String[0]);

}

}

3、创建工厂BaseRepositoryFactory

public class BaseRepositoryFactory, T, ID extends Serializable> extends JpaRepositoryFactoryBean {

public BaseRepositoryFactory(Class extends R> repositoryInterface) {

super(repositoryInterface);

}

@Override

protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {

return new MyRepositoryFactory(em);

}

private static class MyRepositoryFactory extends JpaRepositoryFactory {

private final EntityManager em;

public MyRepositoryFactory(EntityManager em) {

super(em);

this.em = em;

}

@Override

protected Object getTargetRepository(RepositoryInformation information) {

return new BaseRepositoryImpl((Class) information.getDomainType(), em);

}

@Override

protected Class getRepositoryBaseClass(RepositoryMetadata metadata) {

return BaseRepositoryImpl.class;

}

}

}

4、启动类引入

@EnableJpaRepositories(repositoryFactoryBeanClass = BaseRepositoryFactory.class, basePackages ="com.XXX")

@SpringBootApplication

@EnableDiscoveryClient // 即消费也注册

public class SystemApplication {

public static void main(String[] args) {

SpringApplication.run(SystemApplication.class, args);

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值