简体   繁体   中英

creating an auto increment field within a mongo document

In my Spring Boot application I am using Spring-Data MongoDB, and I have a simple POJO that represents users:

@EqualsAndHashCode
public class User implements Storable {

  @Id
  public ObjectId id;

  @Getter @Setter public String firstName;
  @Getter @Setter public String lastName;
  @Getter @Setter public long userNum;
  @DBRef(lazy = true)
  @Getter @Setter public List<Section> sections = new ArrayList<Section>();

... 
rest of class omitted
...

}

my UserController looks something like this:

@Controller
public class UserController {

  @Autowired
  UserRepository repository;

  @ModelAttribute("allSections")
  public List<Section> getSections() {
    return sectionRepository.findAll();
  }

  @RequestMapping(value = "/users/new", method = RequestMethod.POST)
  public String newUser(@ModelAttribute("user") User user) {
    User newUser = new User();
    newUser.userNum = user.userNum;
    newUser.firstName = user.firstName;
    newUser.lastName = user.lastName;
    newUser.sections = user.sections;
    newUser = repository.save(newUser);

    for (Section section : newUser.sections) {
      section.addToUsers(newUser);
      sectionRepository.save(section);
    }

    return "redirect:/users";
  }
... rest of controller omitted 
}

please notice that the field that I want to be auto-generated is not the ID field.

I would like for the userNum attribute to be auto incrementing such that the first user object created and stored in the database starts at a certain value... say 9000 and each user created after that is incremented by 1.

What are my options to do this? I have seen examples using JPA's @GeneratedValue, others that rely on custom Mongo queries to create a sequence collection, but I have not been able to get either to work...

Create Counter collection:

public class Counter {

    @Id
    private String id;

    private long seq;

    public Counter(String id, long seq) {
        this.id = id;
        this.seq = seq;
    }

    // Getters and setters
}

Then a MongoRepository:

@Repository
public interface CounterRepository extends MongoRepository<Counter, String> {}

And a Service/DAO:

@Service
public class CounterServiceImpl implements CounterService {

    @Autowired
    private CounterRepository counterRepository;

    @Override
    public long getNext(String sequenceId) {
        Counter counter = counterRepository.findOne(sequenceId);
        long id = counter.getSeq();
        counter.setSeq(id + 1);
        counterRepository.save(counter);
        return id;
    }
}

Ok I have figured this out here is how I implemented this:

class for userNum, which is a simple POJO

public class UserNum {

  @Id
  private ObjectId id;

  @Getter
  @Setter
  public long seq;

  public UserNum(long seq) {
    this.seq = seq;
  }

}

the UserNumRepository has one method defined that returns the last UserNum that was saved to the collection

@Repository
public interface UserNumRepository extends MongoRepository<UserNum, String> {
  UserNum findTopByOrderByIdDesc();
}

the UserNumService which simply finds the last number in the sequence and creates the next number, then saves it and returns that number. UserNumService is an interface with one method signature. this creates a collection of all userNums that have been created and used.

@Service
public class UserNumServiceImpl implements UserNumService {

  @Autowired
  private UserNumRepository userNumRepository;

  @Override
  public long getNext() {
    UserNum last = userNumRepository.findTopByOrderByIdDesc();
    long lastNum = last.seq;
    UserNum next = new UserNum(lastNum + 1);
    userNumRepository.save(next);
    return next.seq;
  }
}

Inside Application.java you could seed the collection with the starting number or from the mongo shell.

@Autowired UserNumRepository userNumRepository;

public void run(String... args) throws Exception {

    userNumRepository.deleteAll();
    // start the sequence at 9000
    userNumRepository.save(new UserNum(9000)); 
}

and finally now you can simply use the service when needing to issue a new userNum, perhaps inside the constructor.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM