tinmegali
5/14/2019 - 4:08 PM

Spring: MongoDB

  • @Document: Identifies a domain object to be persisted to MongoDB.
  • @Id: Demarcates an identifier.
  • @Indexed(unique = true): Mark a field to be indexed using MongoDB's indexing feature.
  • @TextIndexed: marks a field to be part of the text index. As there can be only one text index per collection all fields marked with {@link TextIndexed} are combined into one single index.
  • @TextScore: marks the property to be considered as the on server calculated when doing full text search. Property will not be written when saving entity.
  • @DBRef: creates a reference with a document saved on another collection.
@Document(collection = "users")
public class User {

    @Id
    private String id;

    @Indexed(unique = true)
    private String username;

    @TextIndexed
    private String firstname;

    @TextIndexed
    private String lastname;

    @TextScore
    private Float textScore;

    private Address homeAddress;

    @DBRef
    private EmailAddress email;
  }
  • Extend CrudRepository or PagingAndSortRepository
  • main functionalities:
    • <S extends T> S save(S entity)
    • Optional<T> findById(ID primaryKey)
    • Iterable<T> findAll()
    • long count()
    • void delete(T entity)
    • boolean existsById(ID primaryKey)
    • Iterable<T> findAll(Sort sort)
    • Page<T> findAll(Pageable pageable)
  • Support json query
public interface UserRepository extends PagingAndSortingRepository<User, String> {

    Page<User> findAllByUsername(@Param("username") String username, Pageable page);
    Page<User> findAllByHomeAddress_City(@Param("city") String city, Pageable page);

    @Query(" {'homeAddress.country' : ?0 } ")
    Page<User> jsonQueryFindByCountry(String country, Pageable page);

    @Query(" { 'username' : ?0 } ")
    Page<User> jsonQueryFindUsernameByRegex(String regex, Pageable page);

    Optional<User> findByEmail_Id(String emailId);

}
  • Extend AbstractMongoEventListener<Document>
  • Override the propper method:
    • onBeforeConvert(BeforeConvertEvent<E> event)
    • onBeforeSave(BeforeSaveEvent<E> event): get entity calling event.getSource. Note: it may not have an id.
    • onAfterSave(AfterSaveEvent<E> event): get entity calling event.getSource.
    • onAfterLoad(AfterLoadEvent<E> event)
    • onAfterConvert(AfterConvertEvent<E> event)
    • onAfterDelete(AfterDeleteEvent<E> event)
    • onBeforeDelete(BeforeDeleteEvent<E> event): get id calling:
public void onAfterSave(AfterSaveEvent<T> event) {
  Document courseClassDoc = event.getSource();
  String classID = courseClassDoc.get("_id").toString();
}
  • Create a @Bean with the listener on a @Configuration file

Listener

public class UserListener extends AbstractMongoEventListener<User> {

    @Autowired
    private EmailRepository emailRepository;

    @Override
    public void onAfterSave(AfterSaveEvent<User> event) {
        User user = event.getSource();
        if (user.getEmail() != null && user.getEmail().getId() != null) {
            Optional<EmailAddress> email = emailRepository.findById(user.getEmail().getId());
            if ( email.isPresent() && !email.get().equals(user.getEmail()) ) {
                EmailAddress updatedEmail = user.getEmail();
                emailRepository.save(updatedEmail);
            }
        }
        super.onAfterSave(event);
    }
}

Configuration

@Configuration
public class MongoConfig {
    @Bean
    public UserListener userListener() {
        return new UserListener();
    }
}
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
    testImplementation 'de.flapdoodle.embed:de.flapdoodle.embed.mongo'
}