spring data mongodb级联操作

这篇文章在  spring data mongodb基础篇 的基础上做的扩展

思路:实现org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener<Object>中的onBeforeConvert()方法,mongodb在保存业务对象之前,会先把业务对象转化为DBObject,通过日志可以发现 onBeforeConvert() 在onBeforeSave()之前调用:所以我们可以在保存对象之前处理关联对象,覆盖 onBeforeConvert() 方法。

更通用的做法是覆盖onApplicationEvent(),这个方法在所有的事件之前都会执行,可以根据不同的事件类型做不同的操作,我们甚至还可以实现级联删除操作。

com.wss.lsl.pay.demo.model.User 实体对象加

@DBRef // mongodb的注解,文档之间建立关联关系,可以认为是关系型数据库中的外键
@CascadeSave // 自定义的注解
@Field("card")
private Card card;

// getter/setter

com.wss.lsl.pay.demo.model.Card实体对象:

@Document(collection = "card")
public class Card {

	@Id
	private String id;   // mongodb的主键
	private String cardNo; // 卡号
	
	// getter/setter
}

自定义的注解com.wss.lsl.pay.demo.common.annotation.CascadeSave

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CascadeSave {
}

com.wss.lsl.pay.demo.listener.CascadeSaveMongoEventListener实现了 AbstractMongoEventListener

package com.wss.lsl.pay.demo.listener;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.util.ReflectionUtils;

import com.mongodb.DBObject;
import com.wss.lsl.pay.demo.common.callback.CascadeSaveCallback;

public class CascadeSaveMongoEventListener extends AbstractMongoEventListener<Object> {
	
	@Autowired
	private MongoTemplate mongoTemplate;
	
	@Override
        public void onBeforeConvert(Object source) {
	        ReflectionUtils.doWithFields(source.getClass(), new CascadeSaveCallback(source, mongoTemplate));	
	        super.onBeforeConvert(source);
        }
}

com.wss.lsl.pay.demo.common.callback.CascadeSaveCallback

package com.wss.lsl.pay.demo.common.callback;

import java.lang.reflect.Field;

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.util.ReflectionUtils;

import com.wss.lsl.pay.demo.common.annotation.CascadeSave;

public class CascadeSaveCallback implements ReflectionUtils.FieldCallback {

	private Object source;
	private MongoTemplate mongoTemplate;

	public CascadeSaveCallback(Object source, MongoTemplate mongoTemplate) {
		super();
		this.source = source;
		this.mongoTemplate = mongoTemplate;
	}

	@Override
	public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
		ReflectionUtils.makeAccessible(field);
		
		if(field.isAnnotationPresent(DBRef.class) && field.isAnnotationPresent(CascadeSave.class)){
			final Object fieldValue = field.get(source);
			
			if(fieldValue != null){
				FieldCallback fc = new FieldCallback();
				ReflectionUtils.doWithFields(fieldValue.getClass(), fc);
				
				mongoTemplate.save(fieldValue);
			}
		}
	}

}

com.wss.lsl.pay.demo.common.callback.FieldCallback

package com.wss.lsl.pay.demo.common.callback;

import java.lang.reflect.Field;

import org.springframework.data.annotation.Id;
import org.springframework.util.ReflectionUtils;

public class FieldCallback implements ReflectionUtils.FieldCallback {

	private boolean isFound;

	@Override
	public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {

		ReflectionUtils.makeAccessible(field);

		if (field.isAnnotationPresent(Id.class)) {
			isFound = true;
		}

	}

	public boolean isFound() {
		return isFound;
	}

}

spring的配置文件applicationContext.xml加

<!-- cascade operation -->
<bean class="com.wss.lsl.pay.demo.listener.CascadeSaveMongoEventListener" />

单元测试:UserRepositoryTest中添加测试方法

// 测试级联操作
@Test
public void testCascade() {	
	User user = new User("有会员卡的用户", 20);
	Card card = new Card("1323232");
	user.setCard(card);		
	
	// 我们只保存了user
	userRepository.save(user);
	// 校验card确实保存进去了:card产生了id
	Assert.assertNotNull(card.getId());		
}

 

你可能感兴趣的:(spring,mongodb,Data,mongodb级联操作)