Этот учебник будет продолжать изучать некоторые из основных особенностей Весенние данные MongoDB – @DBRef аннотация и события жизненного цикла.
2. @DBRef
Структура отображения не поддерживает хранение родительских и детских отношений и встроенные документы в другие документы. Что мы можем сделать, хотя это – мы можем хранить их отдельно и использовать DBRef для обозначения документов.
Когда объект загружается из MongoDB, эти ссылки будут охотно решены, и мы вернем отображенный объект, который выглядит так же, как если бы он хранился встроенным в наш главный документ.
Давайте посмотрим на некоторые код:
@DBRef
private EmailAddress emailAddress;
EmailAddress Похоже:
@Document
public class EmailAddress {
@Id
private String id;
private String value;
// standard getters and setters
}
Обратите внимание, что структура отображения не справляется с каскадными операциями . Так , например, если мы запускаем сохранить на родителе, ребенок не будет сохранен автоматически – мы должны явно вызвать сохранить на ребенка, если мы хотим сохранить его, а также.
Это именно то, где события жизненного цикла пригодятся .
3. События жизненного цикла
Spring Data MongoDB публикует некоторые очень полезные события жизненного цикла , такие как onBeforeConvert, onBeforeSave, onAfterSave, onAfterLoad и наАфтерКонверт.
Чтобы перехватить одно из событий, нам нужно зарегистрировать подкласс АбстрактНаппингEventListener и переопределить один из методов здесь. Когда событие будет отправлено, наш слушатель будет вызван и доменный объект будет передан дюйма
3.1. Основные Каскад Сохранить
Давайте посмотрим на пример, который мы имели ранее – сохранение пользовательские с электронная почтаАдрес . Теперь мы можем слушать onBeforeConvert событие, которое будет вызвано до того, как объект домена переходит в преобразователь:
public class UserCascadeSaveMongoEventListener extends AbstractMongoEventListener
Теперь нам просто нужно зарегистрировать слушателя в МонгоКонфиг :
@Bean
public UserCascadeSaveMongoEventListener userCascadingMongoEventListener() {
return new UserCascadeSaveMongoEventListener();
}
Или как XML:
И у нас есть каскадные семантики все сделано – хотя и только для пользователя.
3.2. Общий каскадный проект
Давайте теперь улучшить предыдущее решение, что делает функциональность каскада общей. Начнем с определения пользовательской аннотации:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CascadeSave {
//
}
Давайте теперь работать над нашим пользовательским слушателем для обработки этих полей в общем и не должны отливок для какой-либо конкретной сущности:
public class CascadeSaveMongoEventListener extends AbstractMongoEventListener {
@Autowired
private MongoOperations mongoOperations;
@Override
public void onBeforeConvert(BeforeConvertEvent event) {
Object source = event.getSource();
ReflectionUtils.doWithFields(source.getClass(),
new CascadeCallback(source, mongoOperations));
}
}
Таким образом, мы используем утилиту отражения из Spring, и мы запускаем наш обратный вызов на всех полях, которые отвечают нашим критериям:
@Override
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
ReflectionUtils.makeAccessible(field);
if (field.isAnnotationPresent(DBRef.class) &&
field.isAnnotationPresent(CascadeSave.class)) {
Object fieldValue = field.get(getSource());
if (fieldValue != null) {
FieldCallback callback = new FieldCallback();
ReflectionUtils.doWithFields(fieldValue.getClass(), callback);
getMongoOperations().save(fieldValue);
}
}
}
Как вы можете видеть, мы ищем поля, которые имеют как DBRef аннотация, а также КаскадСейв . Как только мы найдем эти поля, мы спасем сущность ребенка.
Давайте посмотрим на ФилдКаллбэк класс, который мы используем, чтобы проверить, если ребенок имеет @Id аннотация:
public class FieldCallback implements ReflectionUtils.FieldCallback {
private boolean idFound;
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
ReflectionUtils.makeAccessible(field);
if (field.isAnnotationPresent(Id.class)) {
idFound = true;
}
}
public boolean isIdFound() {
return idFound;
}
}
Наконец, чтобы все это сработало вместе, нам, конечно, нужно электронная почтаАдрес поле, чтобы теперь быть правильно аннотированы:
Давайте теперь посмотрим на сценарий – мы экономим Пользователь с электронная почтаАдрес , и каскады операции сохранения к этой встроенной сущности автоматически:
User user = new User();
user.setName("Brendan");
EmailAddress emailAddress = new EmailAddress();
emailAddress.setValue("[email protected]");
user.setEmailAddress(emailAddress);
mongoTemplate.insert(user);
В этой статье мы проиллюстрировали некоторые интересные особенности Spring Data MongoDB – @DBRef аннотация, события жизненного цикла и как мы можем справиться с каскадированием разумно.
Реализация всех этих примеров и фрагментов кода можно найтиболее на GitHub – это проект на основе Maven, поэтому он должен быть легким для импорта и запуска, как она есть.