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());		
}
相關文章
相關標籤/搜索