栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringDataMongoDB-4

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringDataMongoDB-4

SpringDataMongoDB-4 Lifecycle Events

SpringData MongoDB提供了几个特殊的事件类型,我们可以继承AbstractMongoEventListener 重写他的方法,或者实现ApplicationListener接受MongoMappingEvent事件,就可以做操作了。

由下面的几个事件

  1. AfterLoadEvent
  2. AfterDeleteEvent
  3. BeforeDeleteEvent
  4. BeforeConvertEvent
  5. BeforeSaveEvent
  6. AfterSaveEvent
  7. AfterConvertEvent

可以重写AbstractMongoEventListener的方法来重写。

  • onBeforeConvert: 在insert,insertList,save 在通过MongoConverter转换之前。
  • onBeforeSave: insert,insertList,save在保存到数据库之前。
  • onAfterSave: insert,insertList,save保存之后。
  • onAfterLoad: find,findAndRemove,findOne从数据库拿到数据之后。
  • onAfterConvert: 在Document对象转换为POJO对象之后。

在AbstractMongoEventListener中提供了基本的打日志的功能。实现它,并且添加到Spring中就可以用了。如果需要就重写对应的方法。

Session

在MongoDB3.6版本之后,支持Session了,Session可以保证一个session里面的命令是按照执行的顺序来的。这样可以保证数据的一致性保证。这里说的是Sesison是客户端session。

 @Test
    public void testFind11(){
        // 创建sessio选项
        ClientSessionOptions sessionOptions = ClientSessionOptions.builder()
                .causallyConsistent(true)
                .build();
        // 通过mongoTemplate来创建session,
        Student execute = mongoTemplate.withSession(sessionOptions)
                .execute(new SessionCallback() {
                    @Override
                    public Student doInSession(MongoOperations action) {
						先查询
                        Query query = Query.query(Criteria.where("name").is("小红"));
                        Student one = action.findOne(query, Student.class);
                        // 在创建一个,插入
                        Student student = new Student()
                                .setName(one.getName() + ":" + one.getName())
                                .setScore(one.getScore())
                                .setBook(one.getBook())
                                .setAge(one.getAge());

                        action.insert(student);
                        return one;
                    }
                });
        System.out.println(execute);
    }
事务

使用TransactionTemplate操作,或者使用@Transaction注解。

Spring的事务抽象的很好,只要有专门的AbstractPlatformTransactionManager就可以实现事务的功能。SpringMongoDB也支持这样的功能,支持标准的Spring的事务。如果@Transaction注解控制不太灵活,就可以用TransactionTemplate来做。

  1. 配置专门的AbstractPlatformTransactionManager( MongoTransactionManager)

       @Bean
        public MongoTransactionManager transactionManager(MongoDatabaseFactory mongoDatabaseFactory) {
            return new MongoTransactionManager(mongoDatabaseFactory);
        }
    
  2. 使用

    1. 直接用@Transaction注解

    2. 使用TransactionTemplate来更加精细化的控制。

      它的原理就是把TransactionInterceptor里面的Object invoke(MethodInvocation invocation)单独的拿了出来。并且将执行的地方通过回调函数来留给调用方来实现。它需要AbstractPlatformTransactionManager

         @Test
          public void testTransaction() {
              // 通过MongoTransactionManager来创建TransactionTemplate。
              // mongoTransactionManager是通过@Autowired注入的。
              TransactionTemplate txTemplate = new TransactionTemplate(mongoTransactionManager);
              // 通过execute方法来做事务的执行。
              txTemplate.execute(new TransactionCallbackWithoutResult() {
                  @Override
                  protected void doInTransactionWithoutResult(TransactionStatus status) {
                      List all = mongoTemplate.findAll(Student.class);
                      System.out.println(all.get(0));
                  }
              });
          }
      

      execute方法需要TransactionCallback的参数,Spring提供了TransactionCallbackWithoutResult的抽象类,增加了没有返回值的方法。上面的例子就是使用的是TransactionCallbackWithoutResult

对Repositories的一些补充

MongoDB Repositories-官网连接

Repositories

Repositories在使用的时候需要在配置类上增加EnableMongoRepositories,并且指定它的扫描的包,如果没有指定扫描包,默认就扫描配置类所在的包,也可以继承AbstractMongoClientConfiguration 来指定包

  • 继承AbstractMongoClientConfiguration
@Configuration
@EnableMongoRepositories
class ApplicationConfig extends AbstractMongoClientConfiguration {

  @Override
  protected String getDatabaseName() {
    return "e-store";
  }

  @Override
  protected String getMappingBasePackage() {
    return "com.oreilly.springdata.mongodb";
  }
}
  • 直接使用配置类

    @Configuration
    @EnableMongoRepositories
    class ApplicationConfig{
    }
    

在SpringBoot中可以不用显式的标注。因为它已经搞好了自动配置类。

查询

查询方法前面说过,继承于CrudRepositories,也可以写满足SpringData MongoDB语法规则的方法,我们不需要直接这些方法,它会自动帮我们生成。还可以自己写Repositories的实现类,但是不需要实现接口,方法签名和接口里面规定的一样,实现类的名字是接口的名字+Impl(默认),也可以完成这样的需要。这里需要增加一种,还支持在接口的方法上面增加注解来实现。下面详细的说说这几种方式

  1. 写满足SpringData MongoDB语法规则的方法

    只要满足规则就可以,但是里面也定义了一些关键字,具体看 Supported keywords for query methods-官网,

    同样SpringData MongoDB也支持地理位置的查询,这里就不详细介绍了,具体的可以看Geo-spatial Repository Queries

  2. 可以通过注解类来自定义操作

    支持的操作有,删除,count,exist,查询。

    添加org.springframework.data.mongodb.repository.Query注解在repository的查询方法上,就可以使用原生的mongoDB的语法来做操作,如下:

    public interface StudentCrudRepository extends MongoRepository {
        // 使用原生的方法
        Student findStudentByName(String name);
    	
        // 使用query注解,value表示查询的内容,fields表示要字段展示
        @Query(value = "{name:?0,age:?1}", fields = "{name:1,age:1}")
        Student customerFindStudentByNameAndAge(String name, int age);
    	// 增加了sort的排序,这里的语法都是和mongoDB上的一样的,只是将需要参数传递的部分变为占位符
        @Query(value = "{n" +
                "  $or:[n" +
                "    {name:?0},n" +
                "    {age:?1}n" +
                "  ]n" +
                "}",
                fields = "{n" +
                        "    name:1,n" +
                        "    age:1n" +
                        "}",
                sort = "{n" +
                        "    name:1,n" +
                        "    age:1n" +
                        "}")
        List findByNameAndAge(String name, int age);
    	// 查询删除
        @DeleteQuery(value = "{_id:?0}")
        String deleteId(String id);
       // count查询
        @CountQuery("{name:?0}")
        int countName(String name);
    }
    

    例子中的?0表示占位符,可以利用它来替换json查询语句。参数的下标从0开始

占位符可以使用 SpEL,那就可以用函数,调用方法了,进一步的对参数做处理。

SPEL暴露参数是包装在一个数组里面,下标从0开始

  @Query("{name:?#{[0]}}")  
    List findStudentsByName(String name); // 取第一个数据

    @Query("{name:?#{ [0].replace("红","粉") }}")  // 调用string的replace方法,将小红替换为小粉
    List findStudentsByName1(String name);

测试类

  @Test
    void testDeleteCustomer4() {
        System.out.println(studentCrudRepository.countName("小红"));
    }
    @Test
    void testDeleteCustomer5() {
        studentCrudRepository.findStudentsByName1("小红").forEach(System.out::println);
    }

  1. 聚合操作

    聚合操作也是有注解的,org.springframework.data.mongodb.repository.Aggregation

    相应的实例代码在Aggregation Repository Methods-官网

    因为聚合操作有限制,限制为100M,SpringData MongoDB提供了org.springframework.data.mongodb.repository.Meta,来设置属性。如下:

SpringData MongoDB 就介绍到这里了。文章的内容都是参考官网,写的不全,要是有不理解的地方以官网为准。


关于博客这件事,我是把它当做我的笔记,里面有很多的内容反映了我思考的过程,因为思维有限,不免有些内容有出入,如果有问题,欢迎指出。一同探讨。谢谢。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/851981.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号