Spring Data MongoDB中实现自定义级联的方法详解
前言 Spring Data MongoDB 项目提供与MongoDB文档数据库的集成,Spring与Hibernate集成时,Spring提供了 在使用Spring Data操作MongoDB中:
例如:我们有一个实体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 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |