1. 程式人生 > >java中實現MongoDB主鍵自增

java中實現MongoDB主鍵自增

java中實現MongoDB主鍵自增


1.定義序列實體類SeqInfo: 儲存每個集合的ID記錄

//@Document  把一個java類宣告為mongodb的文件,可以通過collection引數指定這個類對應的文件
@Document(collection = "sequence")
public class SeqInfo {
    @Id
    private String id;//主鍵
    private Long seqId;//序列值
    private String collName;//集合名稱
    ...
    ...

2.自定義註解:AutoIncKey

//標識註解:標識主鍵ID需要自動增長
@Target(ElementType.FIELD)  
@Retention(RetentionPolicy.RUNTIME)  
public @interface AutoIncKey {  

} 

3.定義自動增長ID的監聽器: 在儲存物件時,通過反射方式為其生成ID

//@Component泛指元件,把SaveEventListener 加入容器
@Component
public class SaveEventListener extends AbstractMongoEventListener<Object> {

    @Autowired
    MongoTemplate mongo;

    @Override
    public
void onBeforeConvert(BeforeConvertEvent<Object> event) { final Object source = event.getSource(); if (source != null) { ReflectionUtils.doWithFields(source.getClass(),new ReflectionUtils.FieldCallback(){ @Override public void doWith(Field field)throwsIllegalArgumentException, IllegalAccessException { //將一個欄位設定為可讀寫,主要針對private欄位;
ReflectionUtils.makeAccessible(field); // 如果欄位添加了我們自定義的AutoValue註解 if (field.isAnnotationPresent(AutoIncKey.class) && field.get(source) instanceof Number && field.getLong(source) == 0) { // 設定自增ID field.set(source, getNextAutoId(source.getClass().getSimpleName())); } } }); } } /*1.8 以前實現方法如下 @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, getNextAutoId(source.getClass().getSimpleName())); } } }); } }*/ // 獲取下一個自增ID private Long getNextAutoId(String 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); return seq.getSeqId(); } }

4.定義測試的實體類以及資料訪問類

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

    @AutoIncKey
    @Id
    public long id;
    @Field
    public String name;
    @Field
    public int age;

    public User(String name,int age){
        this.name = name;
        this.age = age;
    }
    ...


public interface UserRepository extends MongoRepository<User, String> {

}

5.測試

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootMongodbApplicationTests {

    @Autowired
    UserRepository userRepository;

    @Test
    public void test(){
        userRepository.deleteAll();

        User user1 = new User("Helen", 18);
        User user2 = new User("Steven", 18);
        userRepository.save(user1);
        userRepository.save(user2);
        System.out.println("Helen的id: "+user1.getId());
        System.out.println("Steven的id: "+user2.getId());
    }
}

6.參考