如何使用jpa实现动态插入与修改
发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,这篇文章给大家分享的是有关如何使用jpa实现动态插入与修改的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。jpa之动态插入与修改(重写save)1.动态插入@Data@Ent
千家信息网最后更新 2025年02月01日如何使用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安全错误
数据库的锁怎样保障安全
ftp服务器客户端是什么
亿网科技服务器怎么样
数据库 标准化
网络安全等级怎么降低
淮北餐饮软件开发定制公司
千名极客汇聚北京共话网络安全
威联通nfs挂载服务器失败
服务器RL30
魔方工作室有服务器吗
云服务器可以做黄昏职业吗
株洲it软件开发工程师速成班
太仓创新软件开发优化
sql数据库业务库
厚溥教育科技是互联网吗
写论文怎样分析数据库
数据安全服务器
规格数据的数据库设计
阿里分布式数据库有哪几种
龙盈软件开发有限公司
内网服务器ssh快速发送文件
电脑服务器上怎么看通了几根宽带
网络服务器是哪个公司生产
软件开发怎么适配电脑分辨率
关于校园网络安全标语
网站管理助手 数据库
连云港软件开发定制平台
拉萨数据库渠道
计算机网络技术的相应职位
梁溪区智能软件开发代理价钱
武装押运网络安全心得体会