欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring Data MongoDB中實現(xiàn)自定義級聯(lián)的方法詳解

 更新時間:2017年11月13日 11:36:34   作者:WebFuse  
這篇文章主要給大家介紹了關(guān)于Spring Data MongoDB中實現(xiàn)自定義級聯(lián)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。

前言

Spring Data MongoDB 項目提供與MongoDB文檔數(shù)據(jù)庫的集成,Spring與Hibernate集成時,Spring提供了org.springframework.orm.hibernate3.HibernateTemplate實現(xiàn)了對數(shù)據(jù)的CRUD操作, Spring Data MongoDB提供了org.springframework.data.mongodb.core.MongoTemplate對MongoDB的CRUD的操作,包括對集成的對象映射文件和POJO之間的CRUD的操作。

在使用Spring Data操作MongoDB中:

  • 在保存一個實體的時候,如果被@DBRef標(biāo)識的類只傳入Id,保存后返回的結(jié)果并沒有全部的引用類內(nèi)容,只有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 方法
}

當(dāng)我們調(diào)用保存方法的時候:

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,然后重寫這些方法,即可以實現(xiàn)。

代碼

/**
 * MongoDB級聯(lián)控制
 * 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));
 }
}
/**
 * 級聯(lián)控制的回調(diào)
 * 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);
   }
  }
 }
 /**
  * 級聯(lián)查詢
  *
  * @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);
   }
  }
 }
 /**
  * 級聯(lián)保存
  *
  * @param field
  * @throws IllegalAccessException
  */
 private void doCascadeSave(Field field) throws IllegalAccessException {
  if (field.isAnnotationPresent(CascadeSave.class)) { //如果有標(biāo)識@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();
 }
}

以上是核心代碼。至此,我們就可以解決上述的問題了。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

參考:http://www.baeldung.com/cascading-with-dbref-and-lifecycle-events-in-spring-data-mongodb

相關(guān)文章

  • 解讀Spring接口方法加@Transactional失效的原因

    解讀Spring接口方法加@Transactional失效的原因

    這篇文章主要介紹了Spring接口方法加@Transactional失效的原因解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java函數(shù)式編程(十一):遍歷目錄

    Java函數(shù)式編程(十一):遍歷目錄

    這篇文章主要介紹了Java函數(shù)式編程(十一):遍歷目錄,本文是系列文章的第11篇,其它文章請參閱本文底部的相關(guān)文章,需要的朋友可以參考下
    2014-09-09
  • Java并發(fā)編程之CountDownLatch原理詳解

    Java并發(fā)編程之CountDownLatch原理詳解

    這篇文章主要介紹了Java并發(fā)編程之CountDownLatch原理詳解,CountDownLatch類中使用了一個繼承自AQS的共享鎖Sync對象,構(gòu)造CountDownLatch對象時會將傳入的線程數(shù)值設(shè)為AQS的state值,需要的朋友可以參考下
    2023-12-12
  • SpringMvc @RequestParam 使用推薦使用包裝類型代替包裝類型

    SpringMvc @RequestParam 使用推薦使用包裝類型代替包裝類型

    這篇文章主要介紹了SpringMvc @RequestParam 使用推薦使用包裝類型代替包裝類型,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-02-02
  • 基于Spring AMQP實現(xiàn)消息隊列的示例代碼

    基于Spring AMQP實現(xiàn)消息隊列的示例代碼

    Spring AMQP作為Spring框架的一部分,是一套用于支持高級消息隊列協(xié)議(AMQP)的工具,AMQP是一種強大的消息協(xié)議,旨在支持可靠的消息傳遞,本文給大家介紹了如何基于Spring AMQP實現(xiàn)消息隊列,需要的朋友可以參考下
    2024-03-03
  • Struts2中圖片以base64方式上傳至數(shù)據(jù)庫

    Struts2中圖片以base64方式上傳至數(shù)據(jù)庫

    這篇文章主要介紹了Struts2中圖片以base64方式上傳至數(shù)據(jù)庫的實現(xiàn)代碼,代碼分為前臺和后臺兩段,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • Spring注解開發(fā)生命周期原理解析

    Spring注解開發(fā)生命周期原理解析

    這篇文章主要介紹了Spring注解開發(fā)生命周期原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-09-09
  • JVM的常用命令匯總

    JVM的常用命令匯總

    監(jiān)測java應(yīng)用,最方便的就是直接使用jdk提供的現(xiàn)成工具,在jdk的安裝的bin目錄下,已經(jīng)提供了多種命令行監(jiān)測工具。本文為大家總結(jié)了幾個JVM的常用命令,需要的可以參考一下
    2022-10-10
  • Mysql中備份表的多種方法

    Mysql中備份表的多種方法

    本文給大家分享Mysql中備份表的四種方法,第一種方式是小表的備份,第二種是對整個數(shù)據(jù)庫的備份與恢復(fù),第三種是對某個數(shù)據(jù)表進行備份,每種方式給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • Java通過try釋放資源的方法

    Java通過try釋放資源的方法

    這篇文章主要介紹了Java通過try釋放資源的方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04

最新評論