diff --git a/orm/README.md b/orm/README.md index ae3fed09..c1194564 100644 --- a/orm/README.md +++ b/orm/README.md @@ -26,7 +26,7 @@ var collection = OrmContext.getOrmManager().getCollection(UserEntity.class) #### 2. Indirect use (middle level API) to access data through the collection's simple wrapper IAccessor and IQuery interfaces - IAccessor is a data access interface - - Inserting data into the database uses the return value of the object's id() method as the primary key + - Inserting data into the database uses the field value of the object's field which marked `@Id` as the primary key ``` OrmContext.getAccessor().insert(obj) ``` diff --git a/orm/README_CN.md b/orm/README_CN.md index 2e45dcfc..dad0f0e2 100644 --- a/orm/README_CN.md +++ b/orm/README_CN.md @@ -25,7 +25,7 @@ var collection = OrmContext.getOrmManager().getCollection(UserEntity.class) #### 2. 间接使用(middle level api),通过collection的简易包装类IAccessor和IQuery接口访问数据 - IAccessor接口,为数据访问接口 - - 插入数据到数据库,会以对象的id()方法的返回值作为主键 + - 插入数据到数据库,会以对象class的@Id字段的值作为主键 ``` OrmContext.getAccessor().insert(obj) ``` diff --git a/orm/src/main/java/com/zfoo/orm/convention/ZfooAnnotationConvention.java b/orm/src/main/java/com/zfoo/orm/convention/ZfooAnnotationConvention.java new file mode 100644 index 00000000..569196a2 --- /dev/null +++ b/orm/src/main/java/com/zfoo/orm/convention/ZfooAnnotationConvention.java @@ -0,0 +1,45 @@ +package com.zfoo.orm.convention; + +import com.zfoo.orm.anno.Id; +import org.bson.BsonType; +import org.bson.codecs.pojo.ClassModelBuilder; +import org.bson.codecs.pojo.Convention; +import org.bson.codecs.pojo.PropertyModelBuilder; +import org.bson.codecs.pojo.annotations.*; + +import java.lang.annotation.Annotation; + +/** + * zfoo注解约定 + * + * @author Sando + * @version 1.0 + * @since 2024/7/30 + */ +public class ZfooAnnotationConvention implements Convention { + public static final ZfooAnnotationConvention INSTANCE = new ZfooAnnotationConvention(); + @Override + public void apply(ClassModelBuilder classModelBuilder) { + for (PropertyModelBuilder propertyModelBuilder : classModelBuilder.getPropertyModelBuilders()) { + processPropertyAnnotations(classModelBuilder, propertyModelBuilder); + } + } + + private void processPropertyAnnotations(final ClassModelBuilder classModelBuilder, + final PropertyModelBuilder propertyModelBuilder) { + for (Annotation annotation : propertyModelBuilder.getReadAnnotations()) { + if (annotation instanceof Id) { + String idPropertyName = classModelBuilder.getIdPropertyName(); + String fieldName = propertyModelBuilder.getName(); + if (idPropertyName != null && !fieldName.equals(idPropertyName)) { + // allow using @Id and @BsonId on same field + String typeName = classModelBuilder.getType().getName(); + throw new IllegalStateException("The class " + + typeName + " has more than one id property. The properties are " + + idPropertyName + " and " + fieldName); + } + classModelBuilder.idPropertyName(fieldName); + } + } + } +} diff --git a/orm/src/main/java/com/zfoo/orm/manager/OrmManager.java b/orm/src/main/java/com/zfoo/orm/manager/OrmManager.java index 41d44096..81c7e8c3 100644 --- a/orm/src/main/java/com/zfoo/orm/manager/OrmManager.java +++ b/orm/src/main/java/com/zfoo/orm/manager/OrmManager.java @@ -30,6 +30,7 @@ import com.zfoo.orm.codec.MapCodecProvider; import com.zfoo.orm.config.CacheStrategy; import com.zfoo.orm.config.OrmConfig; import com.zfoo.orm.config.PersisterStrategy; +import com.zfoo.orm.convention.ZfooAnnotationConvention; import com.zfoo.orm.model.EntityDef; import com.zfoo.orm.model.IEntity; import com.zfoo.orm.model.IndexDef; @@ -40,6 +41,7 @@ import com.zfoo.protocol.exception.RunException; import com.zfoo.protocol.util.*; import org.bson.Document; import org.bson.codecs.configuration.CodecRegistries; +import org.bson.codecs.pojo.Conventions; import org.bson.codecs.pojo.PojoCodecProvider; import org.bson.types.ObjectId; import org.slf4j.Logger; @@ -103,8 +105,11 @@ public class OrmManager implements IOrmManager { allEntityCachesUsableMap.put(entityClass, false); } - var pojoCodecProvider = PojoCodecProvider.builder().automatic(true).register(new MapCodecProvider()).build(); - var codecRegistry = CodecRegistries.fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), CodecRegistries.fromProviders(pojoCodecProvider)); + var pojoCodecProvider = PojoCodecProvider.builder().automatic(true) + .conventions(List.of(Conventions.ANNOTATION_CONVENTION, ZfooAnnotationConvention.INSTANCE)) + .register(new MapCodecProvider()).build(); + var codecRegistry = CodecRegistries.fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), + CodecRegistries.fromProviders(pojoCodecProvider)); var mongoBuilder = MongoClientSettings .builder() @@ -456,10 +461,6 @@ public class OrmManager implements IOrmManager { throw new RunException("orm id field only supports int long float double String ObjectId"); } - if (!idField.getName().equals("id")) { - throw new RunException("@Id filed must name with id"); - } - ReflectionUtils.makeAccessible(idField); ReflectionUtils.setField(idField, entityInstance, idFiledValue); var idMethodOptional = Arrays.stream(ReflectionUtils.getAllMethods(clazz)).filter(it -> it.getName().equalsIgnoreCase("id")) diff --git a/orm/src/test/java/com/zfoo/orm/accessor/IdAnnotationTest.java b/orm/src/test/java/com/zfoo/orm/accessor/IdAnnotationTest.java new file mode 100644 index 00000000..9d1e16e9 --- /dev/null +++ b/orm/src/test/java/com/zfoo/orm/accessor/IdAnnotationTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 The zfoo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + */ + +package com.zfoo.orm.accessor; + +import com.zfoo.orm.OrmContext; +import com.zfoo.orm.entity.MailEntity; +import com.zfoo.protocol.util.StringUtils; +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import java.util.Date; + +@Ignore +public class IdAnnotationTest { + + @Test + public void batchInsertTest() { + var context = new ClassPathXmlApplicationContext("application.xml"); + for (int i = 0; i < 100; i++) { + insertMail(StringUtils.format("mail-{}", i)); + } + } + + public void insertMail(String mailId) { + OrmContext.getAccessor().delete(mailId, MailEntity.class); + var mailEntity = MailEntity.valueOf(mailId, "userName-" + mailId, "content" + mailId, new Date()); + OrmContext.getAccessor().insert(mailEntity); + } +} diff --git a/orm/src/test/java/com/zfoo/orm/entity/MailEntity.java b/orm/src/test/java/com/zfoo/orm/entity/MailEntity.java index e5a69e05..bb4fed38 100644 --- a/orm/src/test/java/com/zfoo/orm/entity/MailEntity.java +++ b/orm/src/test/java/com/zfoo/orm/entity/MailEntity.java @@ -28,7 +28,7 @@ import java.util.Date; public class MailEntity implements IEntity { @Id - private String id; + private String mailId; @Index(ascending = true, unique = false) private String userName; @@ -39,7 +39,7 @@ public class MailEntity implements IEntity { public static MailEntity valueOf(String id, String userName, String content, Date createDate) { var entity = new MailEntity(); - entity.id = id; + entity.mailId = id; entity.userName = userName; entity.content = content; entity.createDate = createDate; @@ -48,15 +48,15 @@ public class MailEntity implements IEntity { @Override public String id() { - return id; + return mailId; } - public String getId() { - return id; + public String getMailId() { + return mailId; } - public void setId(String id) { - this.id = id; + public void setMailId(String mailId) { + this.mailId = mailId; } public String getUserName() {