使用jpa之动态插入与修改(重写save)
程序员文章站
2022-06-22 15:40:58
目录jpa之动态插入与修改(重写save)1.动态插入2.重写save(修改)3.启动类扩展jpa方法,重写save方法为什么要重构save?一、重写save二、扩张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<t, id> extends simplejparepository<t, id> { private final jpaentityinformation<t, ?> entityinformation; private final entitymanager em; @autowired public jparepositoryrebuild( jpaentityinformation<t, ?> entityinformation, entitymanager entitymanager) { super(entityinformation, entitymanager); this.entityinformation = entityinformation; this.em = entitymanager; } /** 通用save方法 :新增/选择性更新 */ @override @transactional public <s extends t> 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<string> 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<t, id> implements jparepository<t, id>, jpaspecificationexecutor<t> { private static final string id_must_not_be_null = "the given id must not be null!"; private final jpaentityinformation<t, ?> entityinformation; private final entitymanager em; private final persistenceprovider provider; @nullable private crudmethodmetadata metadata; public simplejparepository(jpaentityinformation<t, ?> 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<t> 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<t> getdomainclass() { return this.entityinformation.getjavatype(); } private string getdeleteallquerystring() { return queryutils.getquerystring("delete from %s x", this.entityinformation.getentityname()); } @transactional public <s extends t> 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<t extends repository<s, id>, s, id> extends transactionalrepositoryfactorybeansupport<t, s, id> { @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<t, id> extends simplejparepository<t, id> { private final jpaentityinformation<t, ?> entityinformation; private final entitymanager em; @autowired public jparepositoryrebuild(jpaentityinformation<t, ?> entityinformation, entitymanager entitymanager) { super(entityinformation, entitymanager); this.entityinformation = entityinformation; this.em = entitymanager; } /** * 通用save方法 :新增/选择性更新 */ @override @transactional public <s extends t> 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<string> 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<t, id extends serializable> extends jparepository<t, id> { /** * 保存但不覆盖原有数据 * @param entity * @return */ t savenotnull(t entity); }
2、创建baserepositoryimpl方法
@norepositorybean public class baserepositoryimpl<t, id extends serializable> extends simplejparepository<t, id> implements baserepository<t, id> { private final jpaentityinformation<t, ?> entityinformation; private final entitymanager em; public baserepositoryimpl(jpaentityinformation<t, ?> entityinformation, entitymanager entitymanager) { super(entityinformation,entitymanager); this.entityinformation = entityinformation; this.em = entitymanager; } public baserepositoryimpl(class<t> 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<string> 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<r extends jparepository<t, id>, t, id extends serializable> extends jparepositoryfactorybean<r, t, id> { 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); } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
上一篇: 中国加快工业机器人普及速度