千家信息网

如何使用jpa实现动态插入与修改

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,这篇文章给大家分享的是有关如何使用jpa实现动态插入与修改的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。jpa之动态插入与修改(重写save)1.动态插入@Data@Ent
千家信息网最后更新 2026年11月03日如何使用jpa实现动态插入与修改

这篇文章给大家分享的是有关如何使用jpa实现动态插入与修改的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

jpa之动态插入与修改(重写save)

1.动态插入

@Data@Entity@DynamicInsert@Table(name = "cpu_dynamics_information")@EntityListeners(AuditingEntityListener.class)public class CpuDynamicsInformation extends CommonEntity implements Serializable {  private static final long serialVersionUID = -662804563658253624L;  // cpu动态属性  private Integer cpuCore;  // cpu用户使用率  private Double cpuUseRate;  // cpu系统使用率  private Double cpuSysRate;  // cpu等待率  private Double cpuWaitRate;  // cpu空闲率  private Double cpuIdleRate;  // cpu总的使用率  private Double cpuCombineRate;  private Long serverId;}

关键注解:

@DynamicInsert@EntityListeners(AuditingEntityListener.class)

2.重写save(修改)

@SuppressWarnings(value = "all")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]);  }}

3.启动类

@EnableJpaAuditing@SpringBootApplication(exclude = MongoAutoConfiguration.class)@EnableJpaRepositories(    value = {"com.fooww.research.repository", "com.fooww.research.shiro.repository"},    repositoryBaseClass = JpaRepositoryReBuild.class)public class MonitorServerApplication {  public static void main(String[] args) {    SpringApplication.run(MonitorServerApplication.class, args);  }}

关键注释:

  • EnableJpaRepositories 扫描的repository包

  • repositoryBaseClass 重写的save类

  • EnableJpaAuditing 使@EntityListeners(AuditingEntityListener.class) 生效

扩展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 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

@NoRepositoryBeanpublic interface BaseRepository extends JpaRepository {     /**     * 保存但不覆盖原有数据     * @param entity     * @return     */    T saveNotNull(T entity);}

2、创建BaseRepositoryImpl方法

@NoRepositoryBeanpublic 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 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);    }}

感谢各位的阅读!关于"如何使用jpa实现动态插入与修改"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

方法 属性 动态 源码 使用率 代码 关键 内容 对象 数据 方案 更多 篇文章 选择性 更新 消费 选择 不错 合适 实用 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 中智农互联网科技 腾讯阿里互联网科技 互联网科技作文 汇久创客互联网科技 互联网科技论坛 互联网科技公司介绍 互联网金融和金融科技 山东吉时兔互联网科技有限公司 互联网之后的科技是什么 成都铂石互联网科技做什么的 南平创想时代互联网科技有限公司 阿大互联网科技有限公司 华夏恒生互联网科技013171 企晟互联网信息科技有限公司 互联网科技和法律行业 工业互联网等科技实现智能化赋能 互联网金融科技元年 互联网科技年终奖 广州有谷有贝互联网科技有限公司 九思连强互联网电子科技有限公司 科技赋能下的互联网金融 互联网最新的科技有限公司 紫鲸互联网科技 万达互联网科技 人人互联网科技是培训 互联网科技素材视频竖屏 四个字互联网科技公司取名 互联网科技中介 广州燕处互联网科技有限公司 互联网科技手抄报图片
0