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

网友投稿 380 2023-03-18


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

前言

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 {

@Autowired

private MongoOperations mongoOperations;

@Override

public void onAfteApFawvXkfrSave(AfterSaveEvent event) {

super.onAfterSave(event);

Object source = event.getSource();

ReflectionUtils.doWithFields(source.getClass(), new CascadeAfterSaveCallback(source, mongoOperations));

}

@Override

public void onBeforeConvert(BeforeConvertEvent 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 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 souApFawvXkfrce, MongoOperations mongoOperations) {

this.source = source;

this.mongoOperations = mongoOperations;

ApFawvXkf}

@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 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://baeldung.com/cascading-with-dbref-and-lifecycle-events-in-spring-data-mongodb


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:接口管理平台图标(接口管理平台图标含义)
下一篇:开放api网关攻击(api网关开发)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~