spring data mongodb级联操做

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

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

更通用的作法是覆盖onApplicationEvent(),这个方法在全部的事件以前都会执行,能够根据不一样的事件类型作不一样的操做,咱们甚至还能够实现级联删除操做。mongodb

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

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

// getter/setter

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

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

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

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

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.FieldCallbackthis

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加.net

<!-- 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());		
}
相关文章
相关标签/搜索