当前位置: 移动技术网 > IT编程>开发语言>Java > Spring Data MongoDB中实现自定义级联的方法详解

Spring Data MongoDB中实现自定义级联的方法详解

2019年07月19日  | 移动技术网IT编程  | 我要评论

前言

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网