Spring Data MongoDB中实现自定义级联的方法详解
程序员文章站
2023-12-19 22:33:34
前言
spring data mongodb 项目提供与mongodb文档数据库的集成,spring与hibernate集成时,spring提供了org.springfr...
前言
spring data mongodb 项目提供与mongodb文档数据库的集成,spring与hibernate集成时,spring提供了org.springframework.orm.hibernate3.hibernatetemplate
实现了对数据的crud操作, spring data mongodb提供了org.springframework.data.mongodb.core.mongotemplate
对mongodb的crud的操作,包括对集成的对象映射文件和pojo之间的crud的操作。
在使用spring data操作mongodb中:
- 在保存一个实体的时候,如果被@dbref标识的类只传入id,保存后返回的结果并没有全部的引用类内容,只有id。
- 保存实体,不能保存引用实体。
例如:我们有一个实体person,有一个实体emailaddress。
@document(collection = "test_person") public class person { private string name; @dbref private emailaddress emailaddress; ... getter setter 方法 }
@document(collection = "test_email") public class emailaddress { @id private string id; private string value; ... getter setter 方法 }
当我们调用保存方法的时候:
public person test() { person person = new person(); person.setname("test"); emailaddress emailaddress = new emailaddress(); emailaddress.setid("5a05108d4dcc5dece03c9e69"); person.setemailaddress(emailaddress); testrepository.save(person); return person; }
上述的代码中,返回的person只有id,没有emailaddress的其他值。
public person test() { person person = new person(); person.setname("test"); emailaddress emailaddress = new emailaddress(); emailaddress.setname("afafa"); person.setemailaddress(emailaddress); testrepository.save(person); return person; }
上述的代码中,emailaddress不能被保存。
解决
生命周期事件
spring data mongodb中存在一些生命周期事件,如:onbeforeconvert, onbeforesave, onaftersave, onafterload and onafterconvert等。我们可以继承abstractmappingeventlistener,然后重写这些方法,即可以实现。
代码
/** * mongodb级联控制 * created by guanzhenxing on 2017/11/9. */ public class cascadecontrolmongoeventlistener extends abstractmongoeventlistener<object> { @autowired private mongooperations mongooperations; @override public void onaftersave(aftersaveevent<object> event) { super.onaftersave(event); object source = event.getsource(); reflectionutils.dowithfields(source.getclass(), new cascadeaftersavecallback(source, mongooperations)); } @override public void onbeforeconvert(beforeconvertevent<object> event) { super.onbeforeconvert(event); object source = event.getsource(); reflectionutils.dowithfields(source.getclass(), new cascadebeforeconvertcallback(source, mongooperations)); } }
/** * 级联控制的回调 * created by guanzhenxing on 2017/11/10. */ public class cascadeaftersavecallback implements reflectionutils.fieldcallback { private object source; private mongooperations mongooperations; public cascadeaftersavecallback(final object source, final mongooperations mongooperations) { this.source = source; this.mongooperations = mongooperations; } @override public void dowith(final field field) throws illegalargumentexception, illegalaccessexception { reflectionutils.makeaccessible(field); if (field.isannotationpresent(dbref.class)) { final object fieldvalue = field.get(source); //获得值 if (fieldvalue != null) { docascadeload(field); } } } /** * 级联查询 * * @param field */ private void docascadeload(field field) throws illegalaccessexception { object fieldvalue = field.get(source); list<field> idfields = reflectionutil.getannotationfield(fieldvalue, id.class); //该方法是为了获得所有的被@id注解的属性 if (idfields.size() == 1) { //只处理一个id object idvalue = reflectionutil.getfieldvalue(fieldvalue, idfields.get(0).getname()); object value = mongooperations.findbyid(idvalue, fieldvalue.getclass()); //查询获得值 reflectionutil.setfieldvalue(source, field.getname(), value); } } }
public class cascadebeforeconvertcallback implements reflectionutils.fieldcallback { private object source; private mongooperations mongooperations; public cascadebeforeconvertcallback(object source, mongooperations mongooperations) { this.source = source; this.mongooperations = mongooperations; } @override public void dowith(field field) throws illegalargumentexception, illegalaccessexception { reflectionutils.makeaccessible(field); if (field.isannotationpresent(dbref.class)) { final object fieldvalue = field.get(source); //获得值 if (fieldvalue != null) { docascadesave(field); } } } /** * 级联保存 * * @param field * @throws illegalaccessexception */ private void docascadesave(field field) throws illegalaccessexception { if (field.isannotationpresent(cascadesave.class)) { //如果有标识@cascadesave注解 object fieldvalue = field.get(source); list<field> idfields = reflectionutil.getannotationfield(fieldvalue, id.class); if (idfields.size() == 1) { mongooperations.save(fieldvalue); } } } }
@retention(retentionpolicy.runtime) @target(elementtype.field) public @interface cascadesave { }
@configuration public class mongoconfig { @bean public cascadecontrolmongoeventlistener usercascadingmongoeventlistener() { return new cascadecontrolmongoeventlistener(); } }
以上是核心代码。至此,我们就可以解决上述的问题了。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
参考:http://www.baeldung.com/cascading-with-dbref-and-lifecycle-events-in-spring-data-mongodb