Spring-boot mongodb ID自增长注解实现 适用于JDK 1.7和JDK 1.8

开发工具Idea ,JDK1.8

Entity类

SeqInfo.java

package com.gl.springbootdao.mongodb.entity;


import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

/**
 * 模拟序列类
 * @author zxy
 * @date 2018年1月8日
 */
@Getter
@Setter
@ToString
@Document(collection = "sequence")
public class SeqInfo {

    @Id
    private String id;// 主键

    @Field
    private String collName;// 集合名称

    @Field
    private Long seqId;// 序列值

}
User.java
package com.gl.springbootdao.mongodb.entity;

import com.gl.springbootdao.mongodb.annotations.AutoValue;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.io.Serializable;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;


@Document(collection="user")
@Getter
@Setter
@ToString
public class User{

    @Id
    @Field("_id")
    @AutoValue
    private long id;
    @Field("username")
    private String userName;
    @Field("password")
    private String passWord;
    public User() {
        super();
    }

    public User(String userName, String passWord) {
        this.userName = userName;
        this.passWord =passWord;
    }


    /**
     * @CompoundIndex
     复合索引,加复合索引后通过复合索引字段查询将大大提高速度。
     @Document
     @CompoundIndexes({
        @CompoundIndex(name = "age_idx", def = "{'lastName': 1, 'age': -1}")
     })
     public class Person<T extends Address> {
     }
     写法如上,lastName和age将作为复合索引,数字参数指定索引的方向,1为正序,-1为倒序。方向对单键索引和随机存不要紧,但如果你要执行分组和排序操作的时候,它就非常重要了。

     @Transient
     被该注解标注的,将不会被录入到数据库中。只作为普通的javaBean属性。

     */


}

自定义主键注解:

package com.gl.springbootdao.mongodb.annotations;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoValue {
}

自定义监听器类

package com.gl.springbootdao.mongodb.listener;
import com.gl.springbootdao.mongodb.entity.SeqInfo;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener;
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Field;

import org.slf4j.Logger;

import com.gl.springbootdao.mongodb.annotations.AutoValue;

/**
 * 保存文档监听类<br>
 * 在保存对象时,通过反射方式为其生成ID
 * @author zxy
 * @date 2018年1月8日
 */

/**@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注
 * @Document  把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档*/
@Component
public class SaveEventListener extends AbstractMongoEventListener<Object> {
    private final static Logger logger = LoggerFactory.getLogger(SaveEventListener.class);
    @Autowired
    private MongoTemplate mongo;

    /**
     * Captures {@link BeforeConvertEvent}.
     *
     * @param event never {@literal null}.
     * @since 1.8
     */
    @Override
    public void onBeforeConvert(BeforeConvertEvent<Object> event) {
        final Object source = event.getSource();
        if (source != null) {
            ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {
                /** Perform an operation using the given field.
                 * @param field the field to operate on */
                @Override
                public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                    ReflectionUtils.makeAccessible(field);
                    // 如果字段添加了我们自定义的AutoValue注解
                    if (field.isAnnotationPresent(AutoValue.class) && field.get(source) instanceof Number
                            && field.getLong(source) == 0) {
                        // field.get(source) instanceof Number &&
                        // field.getLong(source)==0
                        // 判断注解的字段是否为number类型且值是否等于0.如果大于0说明有ID不需要生成ID
                        // 设置自增ID
                        field.set(source, getNextId(source.getClass().getSimpleName()));
                        logger.debug("集合的ID为======================="+ source);
                    }
                }
            });
        }
    }

    /**
     * @since 1.7
     */
    /*@Override
    public void onBeforeConvert(final Object source) {
        if (source != ) {
            ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() {
                public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                    ReflectionUtils.makeAccessible(field);
                    // 如果字段添加了我们自定义的AutoIncKey注解
                    if (field.isAnnotationPresent(AutoIncKey.class)) {
                        // 设置自增ID
                        field.set(source, getNextId(source.getClass().getSimpleName()));
                    }
                }
            });
        }
    }*/

    /**
     * 获取下一个自增ID
     *
     * @param collName
     *            集合(这里用类名,就唯一性来说最好还是存放长类名)名称
     * @return 序列值
     */
    private Long getNextId(String collName) {
        logger.debug("CollectionsName======================="+collName);
        Query query = new Query(Criteria.where("collName").is(collName));
        Update update = new Update();
        update.inc("seqId", 1);
        FindAndModifyOptions options = new FindAndModifyOptions();
        options.upsert(true);
        options.returnNew(true);
        SeqInfo seq = mongo.findAndModify(query, update, options, SeqInfo.class);
        logger.debug(collName+"集合的ID为======================="+seq.getSeqId());
        return seq.getSeqId();
    }
}

Dao类

package com.gl.springbootdao.mongodb.dao;

import com.gl.springbootdao.mongodb.entity.User;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface UserDao  extends MongoRepository<User,Long> {
    User findUserByUsername(String name);

    void saveUser(User user);

    void updateUser(User user);

    void deleteUserById(Long id);
}
Dao类实现类:

package com.gl.springbootdao.mongodb.dao.impl;

import com.gl.springbootdao.mongodb.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;


@Component
public class UserDaoImpl {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 创建对象
     * @param user
     */
    public void saveUser(User user) {
        mongoTemplate.save(user);
    }

    /**
     * 根据用户名查询对象
     * @param userName
     * @return
     */
    public User findUserByUsername(String userName) {
        Query query=new Query(Criteria.where("userName").is(userName));
        User user =  mongoTemplate.findOne(query , User.class);
        return user;
    }

    /**
     * 更新对象
     * @param user
     */
    public void updateUser(User user) {
        Query query=new Query(Criteria.where("id").is(user.getId()));
        Update update= new Update().set("userName", user.getUserName()).set("passWord", user.getPassWord());
        //更新查询返回结果集的第一条
        mongoTemplate.updateFirst(query,update,User.class);
        //更新查询返回结果集的所有
        // mongoTemplate.updateMulti(query,update,UserEntity.class);
    }

    /**
     * 删除对象
     * @param id
     */
    public void deleteUserById(Long id) {
        Query query=new Query(Criteria.where("id").is(id));
        mongoTemplate.remove(query,User.class);
    }
}
测试类

package com.gl.springbootdao;

import com.gl.springbootdao.mongodb.dao.UserDao;
import com.gl.springbootdao.mongodb.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;

@RunWith(SpringRunner.class)// SpringJUnit支持,由此引入Spring-Test框架支持!
@SpringBootTest(classes = SpringbootDaoApplication.class)
@WebAppConfiguration
@TestPropertySource("classpath:application.properties")
public class mongodbTests {

   @Autowired(required=true)
   private UserDao userDao;

   @Autowired
   private MongoTemplate mongo;


/**mongodb基本操作*/
   @Autowired
   private MongoTemplate mongoTemplate;
   @Test
   public void testSaveUser() throws Exception {
      User user=new User();
      user.setId((long) 1111);
      user.setUserName("test2");
      user.setPassWord("123456");
      userDao.saveUser(user);
   }

   @Test
   public void findUserByUserName(){
      Query query=new Query(Criteria.where("id").is((long) 1111));
      User user =  mongoTemplate.findOne(query , User.class);
      System.out.println("user is "+user);
   }
   @Test
   public void updateUser(){
      User user=new User();
      user.setId((long) 1111);
      user.setUserName("test");
      user.setPassWord("111111");
      userDao.updateUser(user);
   }


   @Test
   public void save() {
      User user=new User();
      /*user.setId(SaveEventListener.getNextId(""));*/
      user.setUserName("2");
      user.setPassWord("123456");
//    userDao.saveUser(user);
      mongo.save(user);
      System.out.println("已生成ID:" + user.getId());
   }

   @Test
   public void deleteUserById(){
      userDao.deleteUserById((long) 1111);
   }

   @Test
   public void contextLoads() {
   }

}
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.gl</groupId>
   <artifactId>springboot-dao</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>

   <name>springboot-dao</name>
   <description>Demo project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.9.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.6</java.version>
   </properties>

   <dependencies>
      <!-- spring boot starter -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
         <exclusions>
            <exclusion>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
         </exclusions>
      </dependency>
    
      <!-- web -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      <!-- test -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>xml-maven-plugin</artifactId>
         <version>1.0</version>
      </dependency>
      <!--引入tomcat依赖,可以自定义启动端口 -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-tomcat</artifactId>
      </dependency>
      <!-- mysql -->
      <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-jdbc</artifactId>
      </dependency>
      <!--mongodb 多数据源配置
      Lombok - 是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,
      可以在编译源码的时候生成对应的方法。简单试了以下这个工具还挺好玩的,加上注解我们就不用手动写 getter\setter、构建方式类似的代码了。

      spring-boot-autoconfigure - 就是spring boot的自动化配置-->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-data-mongodb</artifactId>
      </dependency>
      <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-autoconfigure</artifactId>
         <version>RELEASE</version>
      </dependency>
      <!-- mongodb driver -->
      <dependency>
         <groupId>org.mongodb</groupId>
         <artifactId>mongodb-driver</artifactId>
         <version>3.2.2</version>
      </dependency>
      <!--检测JSON格式的响应数据-->
      <dependency>
         <groupId>com.jayway.jsonpath</groupId>
         <artifactId>json-path</artifactId>
      </dependency>
      <!--安装插件 lombok -->
      <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
      <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <version>1.16.10</version>
         <scope>provided</scope>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>


</project>
springboot配置文件

application.properties

## 开发/测试/生产环境分别对应dev/test/prod,可以自由定义
spring.profiles.active=dev

##spring mvc
mvc.view.prefix= /views/
mvc.view.suffix= .jsp
application-dev.properties

##service
server.port=9082
server.session.timeout=10
server.tomcat.uri-encoding=UTF-8

## mongodb
spring.data.mongodb.uri=mongodb://test:123456@localhost:27017/meetings

猜你喜欢

转载自blog.csdn.net/u013028240/article/details/79011542