如何使用jpa实现动态插入与修改
发表于:2025-11-15 作者:千家信息网编辑
千家信息网最后更新 2025年11月15日,这篇文章给大家分享的是有关如何使用jpa实现动态插入与修改的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。jpa之动态插入与修改(重写save)1.动态插入@Data@Ent
千家信息网最后更新 2025年11月15日如何使用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 JpaRepositoryReBuildextends 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的空属性 Setproperties = 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 SimpleJpaRepositoryimplements 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 JpaRepositoryReBuildextends 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的空属性 Setproperties = 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 BaseRepositoryextends JpaRepository { /** * 保存但不覆盖原有数据 * @param entity * @return */ T saveNotNull(T entity);}
2、创建BaseRepositoryImpl方法
@NoRepositoryBeanpublic class BaseRepositoryImplextends 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); }}感谢各位的阅读!关于"如何使用jpa实现动态插入与修改"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
方法
属性
动态
源码
使用率
代码
关键
内容
对象
数据
方案
更多
篇文章
选择性
更新
消费
选择
不错
合适
实用
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
山东华耀星辉互联网科技有限公司
网络安全重点知识竞赛
接入服务器包括ubs吗
远程抓娃娃app软件开发
无锡校畅互联网科技有限公司
企业网络安全宣传材料
宣威云南众福互联网科技有限公司
人大建议禁游戏服务器
数据服务器的运行情况报告
服务器收条
软件开发行业有没有淡旺季
数据库技术及应用专业课
网络安全信息多久评估一次
pdf卡片数据库deleted
摩尔庄园 切换服务器
修改数据库名称和密码
军工网络安全股有哪些
如何查看服务器证书
网络安全控制审计
兴安盟网络安全宣传
服务器sata硬盘改装
5G网络技术与车联网技术
大华监控服务器硬盘蓝色灯亮
有关医院的数据库作业
如何查看服务器证书
红石服务器TIP
网络安全报告大厅
小学生怎么注意网络安全
rmva打不开数据库
数据库审计旁路阻断功能