diff --git a/orm/src/main/java/com/zfoo/orm/convention/ZfooAnnotationConvention.java b/orm/src/main/java/com/zfoo/orm/convention/AnnotationConvention.java similarity index 52% rename from orm/src/main/java/com/zfoo/orm/convention/ZfooAnnotationConvention.java rename to orm/src/main/java/com/zfoo/orm/convention/AnnotationConvention.java index 569196a2..11c2422d 100644 --- a/orm/src/main/java/com/zfoo/orm/convention/ZfooAnnotationConvention.java +++ b/orm/src/main/java/com/zfoo/orm/convention/AnnotationConvention.java @@ -1,25 +1,39 @@ 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; +import java.lang.reflect.Field; /** - * zfoo注解约定 + * 注解约定 * * @author Sando * @version 1.0 * @since 2024/7/30 */ -public class ZfooAnnotationConvention implements Convention { - public static final ZfooAnnotationConvention INSTANCE = new ZfooAnnotationConvention(); +public class AnnotationConvention implements Convention { + public static final AnnotationConvention INSTANCE = new AnnotationConvention(); + @Override public void apply(ClassModelBuilder classModelBuilder) { + String idPropertyName = classModelBuilder.getIdPropertyName(); + if (idPropertyName != null) { + try { + Field idField = classModelBuilder.getType().getDeclaredField(idPropertyName); + Id annotation = idField.getAnnotation(Id.class); + if (annotation == null) { + throw new RuntimeException("The class " + classModelBuilder.getType().getName() + + " has an id property[name=" + idPropertyName + "] but no @Id annotation"); + } + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + return; + } for (PropertyModelBuilder propertyModelBuilder : classModelBuilder.getPropertyModelBuilders()) { processPropertyAnnotations(classModelBuilder, propertyModelBuilder); } @@ -28,17 +42,10 @@ public class ZfooAnnotationConvention implements Convention { private void processPropertyAnnotations(final ClassModelBuilder classModelBuilder, final PropertyModelBuilder propertyModelBuilder) { for (Annotation annotation : propertyModelBuilder.getReadAnnotations()) { - if (annotation instanceof Id) { - String idPropertyName = classModelBuilder.getIdPropertyName(); + if (annotation.annotationType().equals(Id.class)) { 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); + break; } } } 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 81c7e8c3..f746787e 100644 --- a/orm/src/main/java/com/zfoo/orm/manager/OrmManager.java +++ b/orm/src/main/java/com/zfoo/orm/manager/OrmManager.java @@ -30,7 +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.convention.AnnotationConvention; import com.zfoo.orm.model.EntityDef; import com.zfoo.orm.model.IEntity; import com.zfoo.orm.model.IndexDef; @@ -106,7 +106,7 @@ public class OrmManager implements IOrmManager { } var pojoCodecProvider = PojoCodecProvider.builder().automatic(true) - .conventions(List.of(Conventions.ANNOTATION_CONVENTION, ZfooAnnotationConvention.INSTANCE)) + .conventions(List.of(Conventions.ANNOTATION_CONVENTION, AnnotationConvention.INSTANCE)) .register(new MapCodecProvider()).build(); var codecRegistry = CodecRegistries.fromRegistries(MongoClientSettings.getDefaultCodecRegistry(), CodecRegistries.fromProviders(pojoCodecProvider)); diff --git a/orm/src/test/java/com/zfoo/orm/accessor/IdAnnotationTest.java b/orm/src/test/java/com/zfoo/orm/accessor/IdAnnotationTest.java index 9d1e16e9..5828c2a5 100644 --- a/orm/src/test/java/com/zfoo/orm/accessor/IdAnnotationTest.java +++ b/orm/src/test/java/com/zfoo/orm/accessor/IdAnnotationTest.java @@ -15,7 +15,9 @@ package com.zfoo.orm.accessor; import com.zfoo.orm.OrmContext; import com.zfoo.orm.entity.MailEntity; +import com.zfoo.orm.entity.WrongEntity; import com.zfoo.protocol.util.StringUtils; +import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -38,4 +40,17 @@ public class IdAnnotationTest { var mailEntity = MailEntity.valueOf(mailId, "userName-" + mailId, "content" + mailId, new Date()); OrmContext.getAccessor().insert(mailEntity); } + + @Test + public void wrongCase() { + new ClassPathXmlApplicationContext("application.xml"); + var entity = new WrongEntity(); + Exception exception = null; + try { + OrmContext.getAccessor().insert(entity); + } catch (Exception e) { + exception = e; + } + Assert.assertNotNull(exception); + } } diff --git a/orm/src/test/java/com/zfoo/orm/entity/WrongEntity.java b/orm/src/test/java/com/zfoo/orm/entity/WrongEntity.java new file mode 100644 index 00000000..a8dd9056 --- /dev/null +++ b/orm/src/test/java/com/zfoo/orm/entity/WrongEntity.java @@ -0,0 +1,43 @@ +package com.zfoo.orm.entity; + +import com.zfoo.orm.anno.EntityCache; +import com.zfoo.orm.anno.Id; +import com.zfoo.orm.anno.Index; +import com.zfoo.orm.model.IEntity; +import org.bson.codecs.pojo.annotations.BsonId; + +/** + * 用法有问题的entity + * + * @author Sando + * @version 1.0 + * @since 2024/7/30 + */ +@EntityCache +public class WrongEntity implements IEntity { + @BsonId + private String userName; + @Id + private String mailId; + + @Override + public String id() { + return mailId; + } + + public String getMailId() { + return mailId; + } + + public void setMailId(String mailId) { + this.mailId = mailId; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } +}