diff --git a/mongo-plus-annotation/pom.xml b/mongo-plus-annotation/pom.xml index 4cc4acadef9b7764f7074437b9498de776cdad83..a812b49d04158c183ec5c0db62386da99acd4926 100644 --- a/mongo-plus-annotation/pom.xml +++ b/mongo-plus-annotation/pom.xml @@ -105,7 +105,7 @@ - + diff --git a/mongo-plus-annotation/src/main/java/com/anwen/mongo/enums/AggregateTypeEnum.java b/mongo-plus-annotation/src/main/java/com/anwen/mongo/enums/AggregateTypeEnum.java index 2a5b88c2fe522fa92e8840a1cb301a9453a24bc9..64442d00160be878d17b931487b2ff0450dad951 100644 --- a/mongo-plus-annotation/src/main/java/com/anwen/mongo/enums/AggregateTypeEnum.java +++ b/mongo-plus-annotation/src/main/java/com/anwen/mongo/enums/AggregateTypeEnum.java @@ -27,7 +27,7 @@ public enum AggregateTypeEnum { SAMPLE("sample"), - UNION_WITH("unionWith"), + UNION_WITH("$unionWith"), OUT("out") diff --git a/mongo-plus-annotation/src/main/java/com/anwen/mongo/enums/ExecuteMethodEnum.java b/mongo-plus-annotation/src/main/java/com/anwen/mongo/enums/ExecuteMethodEnum.java new file mode 100644 index 0000000000000000000000000000000000000000..a0a583b2f08db38ac34624ffe73ec1eca95d2eb0 --- /dev/null +++ b/mongo-plus-annotation/src/main/java/com/anwen/mongo/enums/ExecuteMethodEnum.java @@ -0,0 +1,35 @@ +package com.anwen.mongo.enums; + +/** + * 执行器方法枚举 + * + * @author JiaChaoYang + **/ +public enum ExecuteMethodEnum { + + SAVE("executeSave"), + + REMOVE("executeRemove"), + + UPDATE("executeUpdate"), + + QUERY("executeQuery"), + + AGGREGATE("executeAggregate"), + + COUNT("executeCount"), + + BULK_WRITE("executeBulkWrite") + + ; + + private final String method; + + ExecuteMethodEnum(String method) { + this.method = method; + } + + public String getMethod() { + return method; + } +} diff --git a/mongo-plus-annotation/src/main/java/com/anwen/mongo/enums/SpecialConditionEnum.java b/mongo-plus-annotation/src/main/java/com/anwen/mongo/enums/SpecialConditionEnum.java index 9d0f54823357f724c070162b6340c82b87cbbb06..7eb5daa28daca58862591e25b65c8e780374630c 100644 --- a/mongo-plus-annotation/src/main/java/com/anwen/mongo/enums/SpecialConditionEnum.java +++ b/mongo-plus-annotation/src/main/java/com/anwen/mongo/enums/SpecialConditionEnum.java @@ -5,6 +5,8 @@ public enum SpecialConditionEnum { OR("$or"), + AND("$and"), + NOR("$nor"), SET("$set"), diff --git a/mongo-plus-boot-starter/pom.xml b/mongo-plus-boot-starter/pom.xml index 0bb91ce31e72fe7c8159863a182063e66bfd65a6..fb30e75c0b321889861740e7ae44f8e11d2f3932 100644 --- a/mongo-plus-boot-starter/pom.xml +++ b/mongo-plus-boot-starter/pom.xml @@ -134,7 +134,7 @@ - + diff --git a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/config/MongoPlusAutoConfiguration.java b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/config/MongoPlusAutoConfiguration.java index ee21ee78c7e4d00379bded99d1f3f4219515568f..98bfd47a9bd8a6674d35fc0734a37cec66d69bc0 100644 --- a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/config/MongoPlusAutoConfiguration.java +++ b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/config/MongoPlusAutoConfiguration.java @@ -3,16 +3,18 @@ package com.anwen.mongo.config; import com.anwen.mongo.annotation.collection.CollectionName; import com.anwen.mongo.cache.global.HandlerCache; import com.anwen.mongo.cache.global.InterceptorCache; +import com.anwen.mongo.cache.global.ListenerCache; import com.anwen.mongo.conn.CollectionManager; import com.anwen.mongo.conn.ConnectMongoDB; import com.anwen.mongo.convert.CollectionNameConvert; -import com.anwen.mongo.execute.ExecutorFactory; import com.anwen.mongo.handlers.DocumentHandler; import com.anwen.mongo.handlers.MetaObjectHandler; import com.anwen.mongo.interceptor.Interceptor; -import com.anwen.mongo.interceptor.business.BlockAttackInnerInterceptor; -import com.anwen.mongo.interceptor.business.LogInterceptor; +import com.anwen.mongo.listener.Listener; +import com.anwen.mongo.listener.business.BlockAttackInnerListener; +import com.anwen.mongo.listener.business.LogListener; import com.anwen.mongo.manager.MongoPlusClient; +import com.anwen.mongo.mapper.BaseMapper; import com.anwen.mongo.property.MongoDBCollectionProperty; import com.anwen.mongo.property.MongoDBLogProperty; import com.anwen.mongo.service.IService; @@ -42,31 +44,32 @@ import java.util.stream.Collectors; @EnableConfigurationProperties(MongoDBLogProperty.class) public class MongoPlusAutoConfiguration implements InitializingBean { - private final ExecutorFactory factory; - private final MongoPlusClient mongoPlusClient; private final ApplicationContext applicationContext; - private final MongoDBLogProperty mongoDBLogProperty; + private final MongoDBLogProperty mongodbLogProperty; - private final MongoDBCollectionProperty mongoDBCollectionProperty; + private final MongoDBCollectionProperty mongodbCollectionProperty; private final CollectionNameConvert collectionNameConvert; + private final BaseMapper baseMapper; + Logger logger = LoggerFactory.getLogger(MongoPlusAutoConfiguration.class); - public MongoPlusAutoConfiguration(MongoDBLogProperty mongoDBLogProperty, MongoDBCollectionProperty mongoDBCollectionProperty, ExecutorFactory executeFactory, MongoPlusClient mongoPlusClient, ApplicationContext applicationContext, CollectionNameConvert collectionNameConvert) { + public MongoPlusAutoConfiguration(MongoDBLogProperty mongodbLogProperty, MongoDBCollectionProperty mongodbCollectionProperty, BaseMapper baseMapper, MongoPlusClient mongoPlusClient, ApplicationContext applicationContext, CollectionNameConvert collectionNameConvert) { this.mongoPlusClient = mongoPlusClient; this.applicationContext = applicationContext; - this.mongoDBLogProperty = mongoDBLogProperty; - this.mongoDBCollectionProperty = mongoDBCollectionProperty; - this.factory = executeFactory; + this.mongodbLogProperty = mongodbLogProperty; + this.mongodbCollectionProperty = mongodbCollectionProperty; this.collectionNameConvert = collectionNameConvert; setConversion(); setMetaObjectHandler(); setDocumentHandler(); + setListener(); setInterceptor(); + this.baseMapper = baseMapper; } @Override @@ -82,9 +85,8 @@ public class MongoPlusAutoConfiguration implements InitializingBean { serviceImpl.setClazz(clazz); String database = initFactory(clazz); //这里需要将MongoPlusClient给工厂 - factory.setMongoPlusClient(mongoPlusClient); serviceImpl.setDatabase(database); - serviceImpl.setFactory(factory); + serviceImpl.setBaseMapper(baseMapper); } public String initFactory(Class clazz) { @@ -103,11 +105,11 @@ public class MongoPlusAutoConfiguration implements InitializingBean { String database = mongoPlusClient.getBaseProperty().getDatabase(); Arrays.stream(database.split(",")).collect(Collectors.toList()).forEach(db -> { CollectionManager collectionManager = new CollectionManager(mongoPlusClient.getMongoClient(), collectionNameConvert, db); - ConnectMongoDB connectMongoDB = new ConnectMongoDB(mongoPlusClient.getMongoClient(), db, finalCollectionName); + ConnectMongoDB connectMongodb = new ConnectMongoDB(mongoPlusClient.getMongoClient(), db, finalCollectionName); MongoDatabase mongoDatabase = mongoPlusClient.getMongoClient().getDatabase(db); mongoDatabaseList.add(mongoDatabase); if (Objects.equals(db, finalDataBaseName[0])){ - MongoCollection collection = connectMongoDB.open(mongoDatabase); + MongoCollection collection = connectMongodb.open(mongoDatabase); collectionManager.setCollectionMap(finalCollectionName,collection); } put(db,collectionManager); @@ -164,23 +166,33 @@ public class MongoPlusAutoConfiguration implements InitializingBean { } /** - * 从Bean中拿到拦截器 + * 从Bean中拿到监听器 * @author JiaChaoYang * @date 2023/11/22 18:39 */ - private void setInterceptor(){ - List interceptors = new ArrayList<>(); - if (mongoDBLogProperty.getLog()){ - interceptors.add(new LogInterceptor()); + private void setListener(){ + List listeners = new ArrayList<>(); + if (mongodbLogProperty.getLog()){ + listeners.add(new LogListener()); } - if (mongoDBCollectionProperty.getBlockAttackInner()){ - interceptors.add(new BlockAttackInnerInterceptor()); + if (mongodbCollectionProperty.getBlockAttackInner()){ + listeners.add(new BlockAttackInnerListener()); } - Collection interceptorCollection = applicationContext.getBeansOfType(Interceptor.class).values(); - if (CollUtil.isNotEmpty(interceptorCollection)){ - interceptors.addAll(interceptorCollection); + Collection listenerCollection = applicationContext.getBeansOfType(Listener.class).values(); + if (CollUtil.isNotEmpty(listenerCollection)){ + listeners.addAll(listenerCollection); } - InterceptorCache.interceptors = interceptors.stream().sorted(Comparator.comparingInt(Interceptor::getOrder)).collect(Collectors.toList()); + ListenerCache.listeners = listeners.stream().sorted(Comparator.comparingInt(Listener::getOrder)).collect(Collectors.toList()); + } + + /** + * 从Bean中拿到拦截器 + * @author JiaChaoYang + * @date 2024/3/17 0:30 + */ + private void setInterceptor(){ + Collection interceptorCollection = applicationContext.getBeansOfType(Interceptor.class).values(); + InterceptorCache.interceptors = new ArrayList<>(interceptorCollection); } } diff --git a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/config/MongoPlusConfiguration.java b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/config/MongoPlusConfiguration.java index 04669c58ccc40d71005d84cef1b73866d1c82d98..8b7b431c4237f096cf8b27cd821a87c7f7e45706 100644 --- a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/config/MongoPlusConfiguration.java +++ b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/config/MongoPlusConfiguration.java @@ -2,11 +2,13 @@ package com.anwen.mongo.config; import com.anwen.mongo.cache.global.MongoPlusClientCache; import com.anwen.mongo.convert.CollectionNameConvert; -import com.anwen.mongo.execute.ExecutorFactory; -import com.anwen.mongo.interceptor.BaseInterceptor; +import com.anwen.mongo.listener.BaseListener; import com.anwen.mongo.manager.MongoPlusClient; +import com.anwen.mongo.mapper.BaseMapper; +import com.anwen.mongo.mapper.DefaultBaseMapperImpl; import com.anwen.mongo.mapper.MongoPlusMapMapper; import com.anwen.mongo.property.MongoDBCollectionProperty; +import com.anwen.mongo.property.MongoDBConfigurationProperty; import com.anwen.mongo.property.MongoDBConnectProperty; import com.anwen.mongo.toolkit.MongoCollectionUtils; import com.anwen.mongo.toolkit.UrlJoint; @@ -26,16 +28,19 @@ import java.util.Collections; * 连接配置 * @since 2023-02-09 14:27 **/ -@EnableConfigurationProperties(value = {MongoDBConnectProperty.class, MongoDBCollectionProperty.class}) +@EnableConfigurationProperties(value = {MongoDBConnectProperty.class, MongoDBCollectionProperty.class, MongoDBConfigurationProperty.class}) public class MongoPlusConfiguration { private final MongoDBConnectProperty mongoDBConnectProperty; private final MongoDBCollectionProperty mongoDBCollectionProperty; - public MongoPlusConfiguration(MongoDBConnectProperty mongoDBConnectProperty, MongoDBCollectionProperty mongoDBCollectionProperty) { - this.mongoDBConnectProperty = mongoDBConnectProperty; - this.mongoDBCollectionProperty = mongoDBCollectionProperty; + private final MongoDBConfigurationProperty mongoDBConfigurationProperty; + + public MongoPlusConfiguration(MongoDBConnectProperty mongodbConnectProperty, MongoDBCollectionProperty mongodbCollectionProperty, MongoDBConfigurationProperty mongodbConfigurationProperty) { + this.mongoDBConnectProperty = mongodbConnectProperty; + this.mongoDBCollectionProperty = mongodbCollectionProperty; + this.mongoDBConfigurationProperty = mongodbConfigurationProperty; } /** @@ -45,47 +50,54 @@ public class MongoPlusConfiguration { */ @Bean @ConditionalOnMissingBean - public MongoClient mongoClient(){ + public MongoClient mongo(){ return MongoClients.create(MongoClientSettings.builder() - .applyConnectionString(new ConnectionString(new UrlJoint(mongoDBConnectProperty).jointMongoUrl())).commandListenerList(Collections.singletonList(new BaseInterceptor())).build()); + .applyConnectionString(new ConnectionString(new UrlJoint(mongoDBConnectProperty).jointMongoUrl())).commandListenerList(Collections.singletonList(new BaseListener())).build()); + } + + @Bean + @ConditionalOnMissingBean(CollectionNameConvert.class) + public CollectionNameConvert collectionNameConvert(){ + return MongoCollectionUtils.build(mongoDBCollectionProperty.getMappingStrategy()); } @Bean @ConditionalOnMissingBean(MongoPlusClient.class) - public MongoPlusClient mongoPlusClient(MongoClient mongoClient){ + public MongoPlusClient mongoPlusClient(MongoClient mongo,CollectionNameConvert collectionNameConvert){ MongoPlusClient mongoPlusClient = new MongoPlusClient(); - mongoPlusClient.setMongoClient(mongoClient); + mongoPlusClient.setMongoClient(mongo); mongoPlusClient.setBaseProperty(mongoDBConnectProperty); + mongoPlusClient.setCollectionNameConvert(collectionNameConvert); MongoPlusClientCache.mongoPlusClient = mongoPlusClient; + if (mongoDBConfigurationProperty.getBanner()){ + System.out.println("___ ___ ______ _ \n" + + "| \\/ | | ___ \\ | \n" + + "| . . | ___ _ __ __ _ ___ | |_/ / |_ _ ___ \n" + + "| |\\/| |/ _ \\| '_ \\ / _` |/ _ \\| __/| | | | / __|\n" + + "| | | | (_) | | | | (_| | (_) | | | | |_| \\__ \\\n" + + "\\_| |_/\\___/|_| |_|\\__, |\\___/\\_| |_|\\__,_|___/\n" + + " __/ | \n" + + " |___/ "); + } return mongoPlusClient; } @Bean - @ConditionalOnMissingBean(CollectionNameConvert.class) - public CollectionNameConvert collectionNameConvert(){ - return MongoCollectionUtils.build(mongoDBCollectionProperty.getMappingStrategy()); - } - - @Bean - @ConditionalOnMissingBean - public ExecutorFactory executeFactory(CollectionNameConvert collectionNameConvert){ - return ExecutorFactory.builder() - .baseProperty(mongoDBConnectProperty) - .collectionNameConvert(collectionNameConvert) - .build(); + @ConditionalOnMissingBean(BaseMapper.class) + public BaseMapper baseMapper(MongoPlusClient mongoPlusClient){ + return new DefaultBaseMapperImpl(mongoPlusClient); } @Bean("mongoPlusMapMapper") @ConditionalOnMissingBean - public MongoPlusMapMapper mongoPlusMapMapper(ExecutorFactory factory) { - return new MongoPlusMapMapper(factory); + public MongoPlusMapMapper mongoPlusMapMapper(MongoPlusClient mongoPlusClient) { + return new MongoPlusMapMapper(mongoPlusClient); } @Bean("mongoTransactionalAspect") - @Deprecated @ConditionalOnMissingBean - public MongoTransactionalAspect mongoTransactionalAspect(MongoClient mongoClient) { - return new MongoTransactionalAspect(mongoClient); + public MongoTransactionalAspect mongoTransactionalAspect(MongoClient mongo) { + return new MongoTransactionalAspect(mongo); } } diff --git a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/config/OverrideMongoConfiguration.java b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/config/OverrideMongoConfiguration.java index 96140db612d52436cb1a52bd8fa3a4451ce2d592..4c2dc4a35a24570eb8bcffa1c145723de735a7ca 100644 --- a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/config/OverrideMongoConfiguration.java +++ b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/config/OverrideMongoConfiguration.java @@ -6,13 +6,11 @@ import com.mongodb.client.MongoClient; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoClientSettingsBuilderCustomizer; -import org.springframework.context.annotation.DependsOn; /** * 覆盖MongoTemplate的MongoClient * @author JiaChaoYang **/ -@DependsOn("mongoClient") public class OverrideMongoConfiguration extends MongoAutoConfiguration { private final MongoClient mongoClient; diff --git a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/property/MongoDBConfigurationProperty.java b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/property/MongoDBConfigurationProperty.java new file mode 100644 index 0000000000000000000000000000000000000000..45307481acb5953beba75fb22888cc16b53d0e1e --- /dev/null +++ b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/property/MongoDBConfigurationProperty.java @@ -0,0 +1,27 @@ +package com.anwen.mongo.property; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * configuration属性配置 + * + * @author JiaChaoYang + **/ +@ConfigurationProperties(prefix = "mongo-plus.configuration") +public class MongoDBConfigurationProperty { + + /** + * banner打印 + * @author JiaChaoYang + * @date 2024/1/26 21:58 + */ + private Boolean banner = true; + + public Boolean getBanner() { + return banner; + } + + public void setBanner(Boolean banner) { + this.banner = banner; + } +} diff --git a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/transactional/MongoPlusTransactionalManager.java b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/transactional/MongoPlusTransactionalManager.java index 483b4cefa0d75f1f7779d27631a01b748c7ade23..43f6e6ce441124162df0bd4f70ba28330fbf5d20 100644 --- a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/transactional/MongoPlusTransactionalManager.java +++ b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/transactional/MongoPlusTransactionalManager.java @@ -22,15 +22,15 @@ public class MongoPlusTransactionalManager extends AbstractPlatformTransactionMa Logger logger = LoggerFactory.getLogger(MongoPlusTransactionalManager.class); - private final MongoClient mongoClient; + private final MongoClient mongo; - public MongoPlusTransactionalManager(MongoClient mongoClient) { - this.mongoClient = mongoClient; + public MongoPlusTransactionalManager(MongoClient mongo) { + this.mongo = mongo; } @Override protected Object doGetTransaction() throws TransactionException { - return mongoClient.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); + return mongo.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); } @Override diff --git a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/transactional/MongoTransactionManagerAutoConfiguration.java b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/transactional/MongoTransactionManagerAutoConfiguration.java index 9dfcce3abd1e3b83b8c0c86d5341a9220b86afb3..7a85411257b47aea8cefa8c0830a523c4e874f2e 100644 --- a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/transactional/MongoTransactionManagerAutoConfiguration.java +++ b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/transactional/MongoTransactionManagerAutoConfiguration.java @@ -4,7 +4,6 @@ import com.mongodb.client.MongoClient; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.DependsOn; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionManager; @@ -13,7 +12,6 @@ import org.springframework.transaction.TransactionManager; * * @author JiaChaoYang **/ -@DependsOn("mongoClient") public class MongoTransactionManagerAutoConfiguration { private final MongoClient mongoClient; diff --git a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/transactional/MongoTransactionalAspect.java b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/transactional/MongoTransactionalAspect.java index a8ad4139f3ec97fe40c5c8947c70c0a7b220c499..092a7c736fc1db8736b5b91380e7166a4e71aefc 100644 --- a/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/transactional/MongoTransactionalAspect.java +++ b/mongo-plus-boot-starter/src/main/java/com/anwen/mongo/transactional/MongoTransactionalAspect.java @@ -20,11 +20,11 @@ public class MongoTransactionalAspect { private static final Logger logger = LoggerFactory.getLogger(MongoTransactionalAspect.class); - public MongoTransactionalAspect(MongoClient mongoClient) { - this.mongoClient = mongoClient; - } + private final MongoClient mongo; - private final MongoClient mongoClient; + public MongoTransactionalAspect(MongoClient mongo) { + this.mongo = mongo; + } @Around("@annotation(com.anwen.mongo.annotation.transactional.MongoTransactional)") public Object manageTransaction(ProceedingJoinPoint joinPoint) throws Throwable { @@ -50,7 +50,7 @@ public class MongoTransactionalAspect { //获取线程中的session ClientSession session = MongoTransactionContext.getClientSessionContext(); if (session == null) { - session = mongoClient.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); + session = mongo.startSession(ClientSessionOptions.builder().causallyConsistent(true).build()); session.startTransaction(); MongoTransactionStatus status = new MongoTransactionStatus(session); MongoTransactionContext.setTransactionStatus(status); diff --git a/mongo-plus-core/pom.xml b/mongo-plus-core/pom.xml index ee768c0bcdf3260f228b9cc39f7b97a925e617ef..1b5f065f9345c7f0787689730eba0c4407a1996c 100644 --- a/mongo-plus-core/pom.xml +++ b/mongo-plus-core/pom.xml @@ -127,7 +127,7 @@ - + diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/MongoPlusBasicDBObject.java b/mongo-plus-core/src/main/java/com/anwen/mongo/bson/MongoPlusBasicDBObject.java similarity index 53% rename from mongo-plus-core/src/main/java/com/anwen/mongo/conditions/MongoPlusBasicDBObject.java rename to mongo-plus-core/src/main/java/com/anwen/mongo/bson/MongoPlusBasicDBObject.java index 58bde45fddc2af5863027d969388aac8be6ed1a2..d356b44286c10d470b150fce024b0e79d927bce1 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/MongoPlusBasicDBObject.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/bson/MongoPlusBasicDBObject.java @@ -1,15 +1,27 @@ -package com.anwen.mongo.conditions; +package com.anwen.mongo.bson; +import com.anwen.mongo.support.SFunction; import com.mongodb.BasicDBObject; /** + * 支持lambda的BasicDBObject * @author JiaChaoYang - * @project mongo-plus - * @description * @date 2023-11-14 15:01 **/ public class MongoPlusBasicDBObject extends BasicDBObject { + public void put(SFunction key,BasicDBObject value){ + put(key.getFieldNameLine(),value); + } + + public void append(SFunction key,BasicDBObject value){ + super.append(key.getFieldNameLine(),value); + } + + public void get(SFunction key){ + super.get(key.getFieldNameLine()); + } + public void put(String key,BasicDBObject value){ if (containsKey(key)){ super.put(key,new BasicDBObject((BasicDBObject) get(key)){{ diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/bson/MongoPlusDocument.java b/mongo-plus-core/src/main/java/com/anwen/mongo/bson/MongoPlusDocument.java new file mode 100644 index 0000000000000000000000000000000000000000..6eec934a990b17fdede771b80958da3f1893f42c --- /dev/null +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/bson/MongoPlusDocument.java @@ -0,0 +1,42 @@ +package com.anwen.mongo.bson; + +import com.anwen.mongo.support.SFunction; +import org.bson.Document; + +import java.util.Map; + +/** + * 可以使用lambda的Document + * + * @author JiaChaoYang + **/ +public class MongoPlusDocument extends Document { + + public MongoPlusDocument() { + } + + public MongoPlusDocument(String key, Object value) { + super(key, value); + } + + public MongoPlusDocument(Map map) { + super(map); + } + + public void put(SFunction key, Object value){ + super.put(key.getFieldNameLine(),value); + } + + public void append(SFunction key,Object value){ + super.append(key.getFieldNameLine(),value); + } + + public Object get(SFunction key){ + return super.get(key.getFieldNameLine()); + } + + public D get(SFunction key,Class clazz){ + return super.get(key.getFieldNameLine(),clazz); + } + +} diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/build/GroupBuilder.java b/mongo-plus-core/src/main/java/com/anwen/mongo/build/GroupBuilder.java index 2b8648795e9a893b04113f7567a79202f8126b55..1f4e5a0dda2bf187fd56ea44c154ceb2e0514897 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/build/GroupBuilder.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/build/GroupBuilder.java @@ -1,7 +1,7 @@ package com.anwen.mongo.build; +import com.anwen.mongo.bson.MongoPlusBasicDBObject; import com.anwen.mongo.conditions.BuildCondition; -import com.anwen.mongo.conditions.MongoPlusBasicDBObject; import com.anwen.mongo.conditions.accumulator.Accumulator; import com.anwen.mongo.constant.SqlOperationConstant; import com.anwen.mongo.model.GroupField; diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/cache/global/InterceptorCache.java b/mongo-plus-core/src/main/java/com/anwen/mongo/cache/global/InterceptorCache.java index 825280ad0f021867f4fda14d693afa21596ea9d8..7f1a6058fde6d62eab49eb9a5a47b2478e2255ef 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/cache/global/InterceptorCache.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/cache/global/InterceptorCache.java @@ -6,10 +6,9 @@ import java.util.ArrayList; import java.util.List; /** + * 拦截器 + * * @author JiaChaoYang - * @project mongo-plus - * @description 拦截器 - * @date 2023-11-22 17:13 **/ public class InterceptorCache { diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/cache/global/ListenerCache.java b/mongo-plus-core/src/main/java/com/anwen/mongo/cache/global/ListenerCache.java new file mode 100644 index 0000000000000000000000000000000000000000..f8cb392945026a472a3ad2aa98e799e7593d3127 --- /dev/null +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/cache/global/ListenerCache.java @@ -0,0 +1,18 @@ +package com.anwen.mongo.cache.global; + +import com.anwen.mongo.listener.Listener; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author JiaChaoYang + * @project mongo-plus + * @description 监听器 + * @date 2023-11-22 17:13 + **/ +public class ListenerCache { + + public static List listeners = new ArrayList<>(); + +} diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/AbstractChainWrapper.java b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/AbstractChainWrapper.java index 6b92c8f804e2e0ba69614ac6a2a90d18c4a1266d..18c1b65a7c3c3fce80c4d4ff0094c7c33957c690 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/AbstractChainWrapper.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/AbstractChainWrapper.java @@ -6,10 +6,7 @@ import com.anwen.mongo.conditions.interfaces.condition.CompareCondition; import com.anwen.mongo.conditions.interfaces.condition.Order; import com.anwen.mongo.conditions.query.QueryChainWrapper; import com.anwen.mongo.constant.SqlOperationConstant; -import com.anwen.mongo.enums.CompareEnum; -import com.anwen.mongo.enums.LogicTypeEnum; -import com.anwen.mongo.enums.ProjectionEnum; -import com.anwen.mongo.enums.TypeEnum; +import com.anwen.mongo.enums.*; import com.anwen.mongo.support.SFunction; import com.mongodb.BasicDBObject; import org.bson.conversions.Bson; @@ -24,7 +21,7 @@ import java.util.List; * @author JiaChaoYang * @date 2023/6/24/024 0:49 */ -public class AbstractChainWrapper> implements Compare { +public abstract class AbstractChainWrapper> implements Compare { protected final Children typedThis = (Children) this; @@ -214,6 +211,46 @@ public class AbstractChainWrapper column, Object value) { + return condition ? likeLeft(column,value) : typedThis; + } + + @Override + public Children likeLeft(SFunction column, Object value) { + return like(column,"^"+value); + } + + @Override + public Children likeLeft(boolean condition, String column, Object value) { + return condition ? likeLeft(column,value) : typedThis; + } + + @Override + public Children likeLeft(String column, Object value) { + return like(column,"^"+value); + } + + @Override + public Children likeRight(boolean condition, SFunction column, Object value) { + return condition ? likeRight(column,value) : typedThis; + } + + @Override + public Children likeRight(SFunction column, Object value) { + return like(column,value+"$"); + } + + @Override + public Children likeRight(boolean condition, String column, Object value) { + return condition ? likeRight(column,value) : typedThis; + } + + @Override + public Children likeRight(String column, Object value) { + return like(column,value+"$"); + } + @Override public Children in(boolean condition, SFunction column, Collection valueList) { return condition ? in(column,valueList) : typedThis; @@ -577,13 +614,13 @@ public class AbstractChainWrapper compareConditionList){ - this.compareList.add(CompareCondition.builder().type(CompareEnum.QUERY.getKey()).logicType(LogicTypeEnum.OR.getKey()).childCondition(compareConditionList).build()); + this.compareList.add(CompareCondition.builder().condition(QueryOperatorEnum.OR.getValue()).type(CompareEnum.QUERY.getKey()).logicType(LogicTypeEnum.OR.getKey()).childCondition(compareConditionList).build()); return typedThis; } public Children getBaseAndCondition(List compareConditionList){ CompareCondition compareCondition = new CompareCondition(); - compareCondition.setCondition("and"); + compareCondition.setCondition(QueryOperatorEnum.AND.getValue()); compareCondition.setType(CompareEnum.QUERY.getKey()); compareCondition.setLogicType(LogicTypeEnum.AND.getKey()); compareCondition.setChildCondition(compareConditionList); diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/BuildCondition.java b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/BuildCondition.java index e5712766b1a0d498669d99446362ff6fe9dd61ed..3edc3ae523807b4b34d3eece0f19e0ff46740133 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/BuildCondition.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/BuildCondition.java @@ -1,5 +1,6 @@ package com.anwen.mongo.conditions; +import com.anwen.mongo.bson.MongoPlusBasicDBObject; import com.anwen.mongo.conditions.accumulator.Accumulator; import com.anwen.mongo.conditions.interfaces.aggregate.pipeline.AddFields; import com.anwen.mongo.conditions.interfaces.aggregate.pipeline.Projection; @@ -15,7 +16,6 @@ import com.anwen.mongo.toolkit.CollUtil; import com.anwen.mongo.toolkit.ObjectIdUtil; import com.anwen.mongo.toolkit.StringUtils; import com.mongodb.BasicDBObject; -import org.bson.types.ObjectId; import java.util.*; import java.util.stream.Collectors; @@ -57,6 +57,11 @@ public class BuildCondition { compare.setChildCondition(Collections.singletonList(compare)); } put(SpecialConditionEnum.OR.getCondition(), buildOrQueryCondition(compare.getChildCondition())); + } else if (Objects.equals(compare.getLogicType(), LogicTypeEnum.AND.getKey())) { + if (null == compare.getChildCondition() || compare.getChildCondition().isEmpty()) { + compare.setChildCondition(Collections.singletonList(compare)); + } + put(SpecialConditionEnum.AND.getCondition(), buildOrQueryCondition(compare.getChildCondition())); } else if (Objects.equals(compare.getLogicType(), LogicTypeEnum.NOR.getKey())) { put(SpecialConditionEnum.NOR.getCondition(), buildQueryCondition(compare.getChildCondition())); } else if (Objects.equals(compare.getLogicType(), LogicTypeEnum.ELEMMATCH.getKey())) { @@ -86,27 +91,36 @@ public class BuildCondition { */ public static List buildOrQueryCondition(List compareConditionList) { return new ArrayList(){{ - compareConditionList.forEach(compare -> { - add(new MongoPlusBasicDBObject(){{ - if (Objects.equals(compare.getCondition(), QueryOperatorEnum.LIKE.getValue()) && StringUtils.isNotBlank(String.valueOf(compare.getValue()))) { - put(compare.getColumn(), new BasicDBObject(SpecialConditionEnum.REGEX.getCondition(), compare.getValue())); - } else if (Objects.equals(compare.getCondition(), QueryOperatorEnum.AND.getValue())) { - add(buildQueryCondition(compare.getChildCondition())); - } else if (Objects.equals(compare.getCondition(), QueryOperatorEnum.TEXT.getValue())) { - put(SpecialConditionEnum.TEXT.getCondition(), new BasicDBObject(SpecialConditionEnum.SEARCH.getCondition(), compare.getValue())); - IndexConstant.createIndex = compare.getColumn(); - } else if (Objects.equals(compare.getColumn(), SqlOperationConstant._ID)){ - //如果是objectId - if (ObjectId.isValid(String.valueOf(compare.getValue()))){ - put(compare.getColumn(),new BasicDBObject("$"+compare.getCondition(),new ObjectId(String.valueOf(compare.getValue())))); - } else { - put(compare.getColumn(),new BasicDBObject("$"+compare.getCondition(),String.valueOf(compare.getValue()))); - } + compareConditionList.forEach(compare -> add(new MongoPlusBasicDBObject(){{ + if (compare.getCondition().contains(QueryOperatorEnum.LIKE.getValue()) && StringUtils.isNotBlank(String.valueOf(compare.getValue()))) { + put(compare.getColumn(), new BasicDBObject(SpecialConditionEnum.REGEX.getCondition(), compare.getValue())); + } else if (Objects.equals(compare.getCondition(), QueryOperatorEnum.OR.getValue())) { + if (null == compare.getChildCondition() || compare.getChildCondition().isEmpty()) { + compare.setChildCondition(Collections.singletonList(compare)); + } + put(SpecialConditionEnum.OR.getCondition(), buildOrQueryCondition(compare.getChildCondition())); + } else if (Objects.equals(compare.getCondition(), QueryOperatorEnum.AND.getValue())) { + if (null == compare.getChildCondition() || compare.getChildCondition().isEmpty()) { + compare.setChildCondition(Collections.singletonList(compare)); + } + put(SpecialConditionEnum.AND.getCondition(), buildOrQueryCondition(compare.getChildCondition())); + } else if (Objects.equals(compare.getLogicType(), LogicTypeEnum.NOR.getKey())) { + put(SpecialConditionEnum.NOR.getCondition(), buildQueryCondition(compare.getChildCondition())); + } else if (Objects.equals(compare.getLogicType(), LogicTypeEnum.ELEMMATCH.getKey())) { + put(compare.getColumn(),new BasicDBObject(SpecialConditionEnum.ELEM_MATCH.getCondition(),buildQueryCondition(compare.getChildCondition()))); + } else if (Objects.equals(compare.getCondition(), QueryOperatorEnum.TEXT.getValue())) { + put(SpecialConditionEnum.TEXT.getCondition(), new BasicDBObject(SpecialConditionEnum.SEARCH.getCondition(), compare.getValue())); + IndexConstant.createIndex = compare.getColumn(); + } else if (Objects.equals(compare.getColumn(), SqlOperationConstant._ID)) { + if (SpecialConditionEnum.IN.getCondition().equals("$" + compare.getCondition())) { + put(compare.getColumn(), new BasicDBObject("$" + compare.getCondition(), ObjectIdUtil.convertObjectId((Collection)compare.getValue()))); } else { - put(compare.getColumn(), new BasicDBObject("$" + compare.getCondition(), compare.getValue())); + put(compare.getColumn(), new BasicDBObject("$" + compare.getCondition(), ObjectIdUtil.convertObjectId(compare.getValue()))); } - }}); - }); + } else { + put(compare.getColumn(), new BasicDBObject("$" + compare.getCondition(), compare.getValue())); + } + }})); }}; } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/aggregate/LambdaAggregateChainWrapper.java b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/aggregate/LambdaAggregateChainWrapper.java index cbe6bbba03030b8c78211934305111ceaefd49c5..4c3b6957da86c0b0f08ad4760f35daf734203181 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/aggregate/LambdaAggregateChainWrapper.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/aggregate/LambdaAggregateChainWrapper.java @@ -1,6 +1,6 @@ package com.anwen.mongo.conditions.aggregate; -import com.anwen.mongo.execute.ExecutorFactory; +import com.anwen.mongo.mapper.BaseMapper; import java.util.List; @@ -9,20 +9,17 @@ import java.util.List; **/ public class LambdaAggregateChainWrapper extends AggregateChainWrapper> implements ChainAggregate { - private final ExecutorFactory factory; - - private final String database; + private final BaseMapper baseMapper; private final Class clazz; - public LambdaAggregateChainWrapper(ExecutorFactory factory,Class clazz,String database) { - this.factory = factory; + public LambdaAggregateChainWrapper(BaseMapper baseMapper, Class clazz) { + this.baseMapper = baseMapper; this.clazz = clazz; - this.database = database; } @Override public List list() { - return factory.getExecute(database).aggregateList(super.baseAggregateList,super.getBasicDBObjectList(),super.getOptionsBasicDBObject(),clazz); + return baseMapper.aggregateList(this,clazz); } } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/interfaces/Compare.java b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/interfaces/Compare.java index 66668e57362039dff8d0cdee8d62acef4a2438c6..4e592f29a0d81dc9fd24e3bd2c8b5c6ea87838b8 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/interfaces/Compare.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/interfaces/Compare.java @@ -311,6 +311,90 @@ public interface Compare extends Serializable { */ Children like(String column, Object value); + /** + * 左包含(模糊查询) + * @param condition 判断如果为true,则加入此条件,可做判空,即不为空就加入这个条件 + * @param column 列名、字段名 + * @param value 值 + * @return Children + * @author JiaChaoYang + * @date 2023/6/20/020 + */ + Children likeLeft(boolean condition , SFunction column, Object value); + + /** + * 左包含(模糊查询) + * @param column 列名、字段名,lambda方式 + * @param value 值 + * @return Children + * @author JiaChaoYang + * @date 2023/6/20/020 + */ + Children likeLeft(SFunction column, Object value); + + /** + * 左包含(模糊查询) + * @param condition 判断如果为true,则加入此条件,可做判空,即不为空就加入这个条件 + * @param column 列名、字段名 + * @param value 值 + * @return Children + * @author JiaChaoYang + * @date 2023/6/20/020 + */ + Children likeLeft(boolean condition , String column, Object value); + + /** + * 左包含(模糊查询) + * @param column 列名、字段名,lambda方式 + * @param value 值 + * @return Children + * @author JiaChaoYang + * @date 2023/6/20/020 + */ + Children likeLeft(String column, Object value); + + /** + * 右包含(模糊查询) + * @param condition 判断如果为true,则加入此条件,可做判空,即不为空就加入这个条件 + * @param column 列名、字段名 + * @param value 值 + * @return Children + * @author JiaChaoYang + * @date 2023/6/20/020 + */ + Children likeRight(boolean condition , SFunction column, Object value); + + /** + * 右包含(模糊查询) + * @param column 列名、字段名,lambda方式 + * @param value 值 + * @return Children + * @author JiaChaoYang + * @date 2023/6/20/020 + */ + Children likeRight(SFunction column, Object value); + + /** + * 右包含(模糊查询) + * @param condition 判断如果为true,则加入此条件,可做判空,即不为空就加入这个条件 + * @param column 列名、字段名 + * @param value 值 + * @return Children + * @author JiaChaoYang + * @date 2023/6/20/020 + */ + Children likeRight(boolean condition , String column, Object value); + + /** + * 右包含(模糊查询) + * @param column 列名、字段名,lambda方式 + * @param value 值 + * @return Children + * @author JiaChaoYang + * @date 2023/6/20/020 + */ + Children likeRight(String column, Object value); + /** * 多值查询 * @param condition 判断如果为true,则加入此条件,可做判空,即不为空就加入这个条件 diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/interfaces/Inject/InjectQuery.java b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/interfaces/Inject/InjectQuery.java index d0a8e47cf85678f3d4a9a601f5903289c9688fe9..40fa7ed5dbbbd5e11562eba0fa90cbdb8c0b310d 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/interfaces/Inject/InjectQuery.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/interfaces/Inject/InjectQuery.java @@ -407,6 +407,39 @@ public interface InjectQuery extends CommInjectQuery { */ List> queryCommand(String database,String collectionName,String command); + + /** + * 是否存在 + * @param id id + * @return java.lang.Boolean + * @author JiaChaoYang + * @date 2024/2/3 13:42 + */ + Boolean exist(String collectionName,Serializable id); + + Boolean exist(String database,String collectionName,Serializable id); + + /** + * 是否存在 + * @param queryChainWrapper wrapper条件 + * @return java.lang.Boolean + * @author JiaChaoYang + * @date 2024/2/3 13:41 + */ + Boolean exist(String collectionName,QueryChainWrapper,?> queryChainWrapper); + + Boolean exist(String database,String collectionName,QueryChainWrapper,?> queryChainWrapper); + + + /** + * 根据条件修改 + * @author JiaChaoYang + * @date 2024/2/3 13:10 + */ + Boolean update(String collectionName,Map entityMap,QueryChainWrapper,?> queryChainWrapper); + + Boolean update(String database,String collectionName,Map entityMap,QueryChainWrapper,?> queryChainWrapper); + /** * 创建索引 * @param bson 描述索引键的对象,该对象不能为 null diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/interfaces/Query.java b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/interfaces/Query.java index 267c5ee1b53caa96676d7af90002b955ec819ece..106e86647fdee305fea3210238cb42c94c01d1b1 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/interfaces/Query.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/interfaces/Query.java @@ -40,4 +40,8 @@ public interface Query extends Project { */ Children orderByDesc(String column); + Children limit(long limit); + + Children skip(long skip); + } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/query/ChainQuery.java b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/query/ChainQuery.java index 13b00660271742a3a96cc83cc38e28efdc2c6e2b..5f8905bad4475273a5c7e8c3da54522ad8fe9c9b 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/query/ChainQuery.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/query/ChainQuery.java @@ -35,6 +35,7 @@ public interface ChainQuery { * @author JiaChaoYang * @date 2023/7/20 23:12 */ + @Deprecated T limitOne(); /** @@ -56,5 +57,26 @@ public interface ChainQuery { */ PageResult page(Integer pageNum, Integer pageSize); + /** + * 分页 + * @param pageParam 分页参数对象 + * @param recentPageNum 查询最近n页的数据 {参数=null 表示仅查询当前页数据} {参数取值[5-50] 表示查询最近[5-50]页的数据 建议recentPageNum等于10 参考 百度分页检索} + * @return {@link PageResult} + * @author JiaChaoYang + * @date 2023/7/20 23:17 + */ + PageResult page(PageParam pageParam, Integer recentPageNum); + + /** + * 分页 + * @param pageNum 当前页 + * @param pageSize 每页显示行数 + * @param recentPageNum 查询最近n页的数据 {参数=null 表示仅查询当前页数据} {参数取值[5-50] 表示查询最近[5-50]页的数据 建议recentPageNum等于10 参考 百度分页检索} + * @return {@link PageResult} + * @author JiaChaoYang + * @date 2023/7/20 23:17 + */ + PageResult page(Integer pageNum, Integer pageSize, Integer recentPageNum); + long count(); } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/query/LambdaQueryChainWrapper.java b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/query/LambdaQueryChainWrapper.java index 47391caec36bcb33676b0ea1c99ec9ca00da6311..3f26134b483afed89398d7ebbe5c3f471503d686 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/query/LambdaQueryChainWrapper.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/query/LambdaQueryChainWrapper.java @@ -1,6 +1,6 @@ package com.anwen.mongo.conditions.query; -import com.anwen.mongo.execute.ExecutorFactory; +import com.anwen.mongo.mapper.BaseMapper; import com.anwen.mongo.model.PageParam; import com.anwen.mongo.model.PageResult; @@ -13,46 +13,54 @@ import java.util.List; */ public class LambdaQueryChainWrapper extends QueryChainWrapper> implements ChainQuery { - private final ExecutorFactory factory; + private final BaseMapper baseMapper; private final Class clazz; - private final String database; - - public LambdaQueryChainWrapper(ExecutorFactory factory, Class clazz,String database){ - this.factory = factory; + public LambdaQueryChainWrapper(BaseMapper baseMapper, Class clazz){ + this.baseMapper = baseMapper; this.clazz = clazz; - this.database = database; } @Override public List list() { - return factory.getExecute(database).list(getCompareList(), getOrderList(),getProjectionList(),getBasicDBObjectList(),clazz); + return baseMapper.list(this,clazz); } @Override public T one() { - return factory.getExecute(database).one(getCompareList(),getProjectionList(),getBasicDBObjectList(),clazz); + return baseMapper.one(this,clazz); } @Override + @Deprecated public T limitOne() { - return factory.getExecute(database).limitOne(getCompareList(),getProjectionList(),getBasicDBObjectList(),getOrderList(),clazz); + return baseMapper.limitOne(this,clazz); } @Override public PageResult page(PageParam pageParam) { - return factory.getExecute(database).page(getCompareList(),getOrderList(),getProjectionList(),getBasicDBObjectList(),pageParam.getPageNum(),pageParam.getPageSize(),clazz); + return baseMapper.page(this,pageParam.getPageNum(),pageParam.getPageSize(),clazz); } @Override public PageResult page(Integer pageNum, Integer pageSize) { - return factory.getExecute(database).page(getCompareList(),getOrderList(),getProjectionList(),getBasicDBObjectList(),pageNum,pageSize,clazz); + return baseMapper.page(this,pageNum,pageSize,clazz); + } + + @Override + public PageResult page(PageParam pageParam, Integer recentPageNum) { + return baseMapper.page(this, pageParam.getPageNum(), pageParam.getPageSize(), recentPageNum, clazz); + } + + @Override + public PageResult page(Integer pageNum, Integer pageSize, Integer recentPageNum) { + return baseMapper.page(this, pageNum, pageSize, recentPageNum, clazz); } @Override public long count() { - return factory.getExecute(database).count(getCompareList(),clazz); + return baseMapper.count(this,clazz); } } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/query/QueryChainWrapper.java b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/query/QueryChainWrapper.java index 3c0d1cbfc966dc0a14ea37e66dba85cc6d2aeb60..2d44d4c1052a5a179e6a2227abad36f818ce8ee6 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/query/QueryChainWrapper.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/query/QueryChainWrapper.java @@ -8,7 +8,12 @@ import com.anwen.mongo.support.SFunction; import java.util.List; -public class QueryChainWrapper> extends AbstractChainWrapper implements Query { +/** + * AbstractChainWrapper的条件扩展类,查询专有的条件,使用类构造条件时,使用QueryChainWrapper的子类,{@link QueryWrapper} + * @author JiaChaoYang + * @date 2024/2/3 13:10 +*/ +public abstract class QueryChainWrapper> extends AbstractChainWrapper implements Query { @Override public Children project(Projection... projection) { @@ -94,4 +99,14 @@ public class QueryChainWrapper> return getBaseOrder(OrderEnum.ORDER_BY_DESC.getFlag(), column); } + @Override + public Children limit(long limit) { + return null; + } + + @Override + public Children skip(long skip) { + return null; + } + } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/update/LambdaUpdateChainWrapper.java b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/update/LambdaUpdateChainWrapper.java index b8d6a5823bcd949eac3d0df7b840cd3d547c681a..c91b4f55c710b0c06c1810f29351b3d89362879f 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/update/LambdaUpdateChainWrapper.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/conditions/update/LambdaUpdateChainWrapper.java @@ -1,36 +1,26 @@ package com.anwen.mongo.conditions.update; -import com.anwen.mongo.conditions.interfaces.condition.CompareCondition; -import com.anwen.mongo.execute.ExecutorFactory; - -import java.util.ArrayList; -import java.util.List; +import com.anwen.mongo.mapper.BaseMapper; public class LambdaUpdateChainWrapper extends UpdateChainWrapper> implements ChainUpdate { - private final ExecutorFactory factory; + private final BaseMapper baseMapper; private final Class clazz; - private final String database; - - public LambdaUpdateChainWrapper(ExecutorFactory factory,Class clazz,String database) { - this.factory = factory; + public LambdaUpdateChainWrapper(BaseMapper baseMapper, Class clazz) { + this.baseMapper = baseMapper; this.clazz = clazz; - this.database = database; } @Override public boolean update(){ - List compareConditionList = new ArrayList<>(); - compareConditionList.addAll(getCompareList()); - compareConditionList.addAll(getUpdateCompareList()); - return factory.getExecute(database).update(compareConditionList,clazz); + return baseMapper.update(this,clazz); } @Override public boolean remove() { - return factory.getExecute(database).remove(getCompareList(),clazz); + return baseMapper.remove(this,clazz); } } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/convert/Converter.java b/mongo-plus-core/src/main/java/com/anwen/mongo/convert/Converter.java index 3dec64565d0879b734786c3bcd89680839306c41..a28dfc73cd8abb895e5c5b3afa291afbd0141e32 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/convert/Converter.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/convert/Converter.java @@ -1,6 +1,7 @@ package com.anwen.mongo.convert; import com.anwen.mongo.cache.global.PropertyCache; +import com.anwen.mongo.toolkit.InstantUtil; import com.anwen.mongo.toolkit.StringUtils; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCursor; @@ -8,6 +9,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -18,11 +20,12 @@ public class Converter { /** * 将FindIterable转换为List>。 + * * @param iterable 待转换的FindIterable对象 - * @return java.util.List> 转换后的List>对象 + * @return java.util.List> 转换后的List>对象 * @author JiaChaoYang * @date 2023/6/29/029 - */ + */ public static List> convertDocumentToMap(FindIterable iterable) { List> resultList = new ArrayList<>(); try (MongoCursor cursor = iterable.iterator()) { @@ -41,24 +44,30 @@ public class Converter { return resultList; } - public static List> convertDocumentToMap(FindIterable iterable,Integer total) { + public static List> convertDocumentToMap(FindIterable iterable, Integer total) { List> resultList = new ArrayList<>(total); - for (Map map : iterable.batchSize(total)) { + for (Map map : iterable.batchSize(total)) { resultList.add(convertKeysToCamelCase(map)); } return resultList; } public static Map convertKeysToCamelCase(Map map) { - if (!PropertyCache.mapUnderscoreToCamelCase){ - return map; - } return map.entrySet().stream() .collect(Collectors.toMap( - entry -> StringUtils.convertToCamelCase(entry.getKey()), - Map.Entry::getValue) - ); + entry -> convertToCamelCaseIfNeeded(entry.getKey()), + entry -> convertValue(entry.getValue()) + )); } + private static String convertToCamelCaseIfNeeded(String key) { + return PropertyCache.mapUnderscoreToCamelCase ? StringUtils.convertToCamelCase(key) : key; + } + private static Object convertValue(Object value) { + if (value instanceof Date) { + return InstantUtil.convertTimestampToLocalDateTime(((Date) value).toInstant()); + } + return value; + } } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/domain/MongoPlusException.java b/mongo-plus-core/src/main/java/com/anwen/mongo/domain/MongoPlusException.java new file mode 100644 index 0000000000000000000000000000000000000000..db205e932ecf99e2024a45c1f15e7768a7cfaa31 --- /dev/null +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/domain/MongoPlusException.java @@ -0,0 +1,11 @@ +package com.anwen.mongo.domain; + +/** + * MongoPlus异常 + * + * @author JiaChaoYang + **/ +public class MongoPlusException extends RuntimeException { + + +} diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/execute/AbstractExecute.java b/mongo-plus-core/src/main/java/com/anwen/mongo/execute/AbstractExecute.java index db3491134602577df924b52809d11c342c50e91d..047ed85c26930d216ac6860e66d5d6a75e859a5c 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/execute/AbstractExecute.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/execute/AbstractExecute.java @@ -3,9 +3,12 @@ package com.anwen.mongo.execute; import com.anwen.mongo.annotation.ID; import com.anwen.mongo.cache.global.HandlerCache; import com.anwen.mongo.conditions.BuildCondition; +import com.anwen.mongo.conditions.aggregate.AggregateChainWrapper; import com.anwen.mongo.conditions.interfaces.aggregate.pipeline.Projection; import com.anwen.mongo.conditions.interfaces.condition.CompareCondition; import com.anwen.mongo.conditions.interfaces.condition.Order; +import com.anwen.mongo.conditions.query.QueryChainWrapper; +import com.anwen.mongo.conditions.update.UpdateChainWrapper; import com.anwen.mongo.conn.CollectionManager; import com.anwen.mongo.constant.SqlOperationConstant; import com.anwen.mongo.context.MongoTransactionContext; @@ -20,11 +23,12 @@ import com.anwen.mongo.strategy.convert.ConversionService; import com.anwen.mongo.support.SFunction; import com.anwen.mongo.toolkit.*; import com.mongodb.BasicDBObject; +import com.mongodb.bulk.BulkWriteResult; import com.mongodb.client.AggregateIterable; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.model.*; -import com.mongodb.client.result.InsertOneResult; +import com.mongodb.client.result.InsertManyResult; import org.bson.Document; import org.bson.conversions.Bson; import org.bson.types.ObjectId; @@ -52,13 +56,6 @@ public abstract class AbstractExecute implements Execute { private final Logger logger = LoggerFactory.getLogger(AbstractExecute.class); - /** - * 计数id - * @author JiaChaoYang - * @date 2023/12/28 11:33 - */ - private int num = 1; - private final CollectionManager collectionManager; private final CollectionNameConvert collectionNameConvert; @@ -73,9 +70,9 @@ public abstract class AbstractExecute implements Execute { public boolean save(T entity){ try { Document document = processIdField(entity,false); - InsertOneResult insertOneResult = doSave(document, collectionManager.getCollection(ClassTypeUtil.getClass(entity))); + InsertManyResult insertManyResult = executeSave(Collections.singletonList(document), collectionManager.getCollection(ClassTypeUtil.getClass(entity))); setBackIdValue(document, entity); - return insertOneResult.wasAcknowledged(); + return insertManyResult.wasAcknowledged(); } catch (Exception e) { logger.error("save fail , error info : {}", e.getMessage(), e); return false; @@ -86,7 +83,7 @@ public abstract class AbstractExecute implements Execute { try { List documentList = processIdFieldList(entityList); MongoCollection collection = collectionManager.getCollection(entityList.iterator().next().getClass()); - return doSaveBatch(documentList,collection).getInsertedIds().size() == entityList.size(); + return executeSave(documentList,collection).getInsertedIds().size() == entityList.size(); } catch (Exception e) { logger.error("saveBatch fail , error info : {}", e.getMessage(), e); return false; @@ -101,55 +98,72 @@ public abstract class AbstractExecute implements Execute { return isExist(idByEntity,entity.getClass()) ? updateById(entity) : save(entity); } - public Boolean saveOrUpdateWrapper(T entity,List compareConditionList){ - long count = count(compareConditionList, entity.getClass()); + public Boolean saveOrUpdateWrapper(T entity,QueryChainWrapper queryChainWrapper){ + long count = count(queryChainWrapper, entity.getClass()); if (count > 0){ - BasicDBObject queryBasic = BuildCondition.buildQueryCondition(compareConditionList); - Document document = DocumentUtil.checkUpdateField(entity,false); - document.remove(SqlOperationConstant._ID); - BasicDBObject updateField = new BasicDBObject(SpecialConditionEnum.SET.getCondition(), document); - return executeUpdate(queryBasic,updateField,collectionManager.getCollection(ClassTypeUtil.getClass(entity))).getModifiedCount() >= 1; + MutablePair updatePair = getUpdateCondition(queryChainWrapper.getCompareList(), entity); + return executeUpdate(updatePair.getLeft(),updatePair.getRight(),collectionManager.getCollection(ClassTypeUtil.getClass(entity))).getModifiedCount() >= 1; } return save(entity); } public Boolean saveOrUpdateBatch(Collection entityList) { - List saveList = new ArrayList<>(); - List updateList = new ArrayList<>(); - entityList.parallelStream().forEach(entity -> { + List> writeModelList = new ArrayList<>(); + entityList.forEach(entity -> { String idByEntity = ClassTypeUtil.getIdByEntity(entity, true); - if ((StringUtils.isBlank(idByEntity) || !isExist(idByEntity, entity.getClass()))) { - saveList.add(entity); + if (StringUtils.isBlank(idByEntity)){ + writeModelList.add(new InsertOneModel<>(processIdField(entity,false))); } else { - updateList.add(entity); + MutablePair basicDBObjectPair = getUpdate(entity); + writeModelList.add(new UpdateManyModel<>(basicDBObjectPair.getLeft(),basicDBObjectPair.getRight())); } }); - boolean save = false; - boolean update = false; - if (!saveList.isEmpty()){ - save = saveBatch(saveList); - } - if (!updateList.isEmpty()){ - update = updateBatchByIds(updateList); - } - return save == update; + BulkWriteResult bulkWriteResult = executeBulkWrite(writeModelList,collectionManager.getCollection(entityList.stream().findFirst().get().getClass())); + return (bulkWriteResult.getModifiedCount() + bulkWriteResult.getInsertedCount()) == entityList.size(); + } + + public Boolean saveOrUpdateBatchWrapper(Collection entityList,QueryChainWrapper queryChainWrapper){ + Class clazz = entityList.stream().findFirst().get().getClass(); + List> writeModelList = new ArrayList<>(); + entityList.forEach(entity -> { + long count = count(queryChainWrapper, clazz); + if (count > 0){ + MutablePair updatePair = getUpdateCondition(queryChainWrapper.getCompareList(), entity); + writeModelList.add(new UpdateManyModel<>(updatePair.getLeft(),updatePair.getRight())); + } else { + writeModelList.add(new InsertOneModel<>(processIdField(entity,false))); + } + }); + BulkWriteResult bulkWriteResult = executeBulkWrite(writeModelList, collectionManager.getCollection(clazz)); + return (bulkWriteResult.getModifiedCount() + bulkWriteResult.getInsertedCount()) == entityList.size(); } + public Boolean update(T entity,QueryChainWrapper queryChainWrapper){ + MutablePair updatePair = getUpdateCondition(queryChainWrapper.getCompareList(), entity); + return executeUpdate(updatePair.getLeft(),updatePair.getRight(),collectionManager.getCollection(entity.getClass())).getModifiedCount() > 0; + } public Boolean updateById(T entity) { - Document document = DocumentUtil.checkUpdateField(entity,false); - BasicDBObject filter = ExecuteUtil.getFilter(document); - BasicDBObject update = new BasicDBObject(SpecialConditionEnum.SET.getCondition(), document); + MutablePair basicDBObjectPair = getUpdate(entity); MongoCollection collection = collectionManager.getCollection(ClassTypeUtil.getClass(entity)); - return executeUpdate(filter,update,collection).getModifiedCount() >= 1; + return executeUpdate(basicDBObjectPair.getLeft(),basicDBObjectPair.getRight(),collection).getModifiedCount() >= 1; } public Boolean updateBatchByIds(Collection entityList) { - int line = 0; - for (T entity : entityList) { - line += updateById(entity) ? 1 : 0; - } - return line == entityList.size(); + List> writeModelList = new ArrayList<>(); + entityList.forEach(entity -> { + MutablePair basicDBObjectPair = getUpdate(entity); + writeModelList.add(new UpdateManyModel<>(basicDBObjectPair.getLeft(),basicDBObjectPair.getRight())); + }); + BulkWriteResult bulkWriteResult = executeBulkWrite(writeModelList,collectionManager.getCollection(entityList.stream().findFirst().get().getClass())); + return bulkWriteResult.getModifiedCount() == entityList.size(); + } + + public MutablePair getUpdate(T entity){ + Document document = DocumentUtil.checkUpdateField(entity,false); + BasicDBObject filter = ExecuteUtil.getFilter(document); + BasicDBObject update = new BasicDBObject(SpecialConditionEnum.SET.getCondition(), document); + return new MutablePair<>(filter,update); } public Boolean updateByColumn(T entity, SFunction column) { @@ -166,10 +180,10 @@ public abstract class AbstractExecute implements Execute { } public Boolean removeById(Serializable id, Class clazz) { - return executeRemove( id, collectionManager.getCollection(clazz)); + return buildRemove( id, collectionManager.getCollection(clazz)); } - private Boolean executeRemove(Serializable id, MongoCollection collection) { + private Boolean buildRemove(Serializable id, MongoCollection collection) { Bson filterId = Filters.eq(SqlOperationConstant._ID, ObjectId.isValid(String.valueOf(id)) ? new ObjectId(String.valueOf(id)) : id); return executeRemove(filterId,collection).getDeletedCount() >= 1; } @@ -200,63 +214,80 @@ public abstract class AbstractExecute implements Execute { } public List list(Class clazz) { - return DocumentMapperConvert.mapDocumentList(doList(collectionManager.getCollection(clazz)),clazz); + return DocumentMapperConvert.mapDocumentList(executeQuery(null,null,null,collectionManager.getCollection(clazz),Document.class),clazz); } - public List list(List compareConditionList, List orderList, List projectionList, List basicDBObjectList, Class clazz) { - BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(compareConditionList, orderList, projectionList, basicDBObjectList); - return lambdaOperate.getLambdaQueryResult(doList(baseLambdaQuery.getCondition(),baseLambdaQuery.getProjection(),baseLambdaQuery.getSort(),collectionManager.getCollection(clazz)),clazz); + public List list(QueryChainWrapper queryChainWrapper, Class clazz) { + BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(queryChainWrapper.getCompareList(),queryChainWrapper.getOrderList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList()); + return lambdaOperate.getLambdaQueryResult(executeQuery(baseLambdaQuery.getCondition(),baseLambdaQuery.getProjection(),baseLambdaQuery.getSort(),collectionManager.getCollection(clazz),Document.class),clazz); } - public List aggregateList(List aggregateList, List basicDBObjectList, BasicDBObject optionsBasicDBObject, Class clazz){ + public List aggregateList(AggregateChainWrapper queryChainWrapper, Class clazz){ + List aggregateList = queryChainWrapper.getBaseAggregateList(); + List basicDBObjectList = queryChainWrapper.getBasicDBObjectList(); + BasicDBObject optionsBasicDBObject = queryChainWrapper.getOptionsBasicDBObject(); List aggregateConditionList = new ArrayList() {{ aggregateList.forEach(aggregate -> add(new AggregateBasicDBObject("$" + aggregate.getType(), aggregate.getPipelineStrategy().buildAggregate(),aggregate.getOrder()))); addAll(basicDBObjectList); }}; aggregateConditionList.sort(Comparator.comparingInt(AggregateBasicDBObject::getOrder)); - AggregateIterable aggregateIterable = doAggregateList(aggregateConditionList, collectionManager.getCollection(clazz)); + AggregateIterable aggregateIterable = executeAggregate(aggregateConditionList, collectionManager.getCollection(clazz),Document.class); aggregateOptions(aggregateIterable,optionsBasicDBObject); return DocumentMapperConvert.mapDocumentList(aggregateIterable.iterator(),clazz); } - public T one(List compareConditionList,List projectionList,List basicDBObjectList,Class clazz) { - BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(compareConditionList, null, projectionList, basicDBObjectList); - List result = lambdaOperate.getLambdaQueryResult(doList(baseLambdaQuery.getCondition(),baseLambdaQuery.getProjection(),baseLambdaQuery.getSort(),collectionManager.getCollection(clazz)),clazz); + public T one(QueryChainWrapper queryChainWrapper,Class clazz) { + BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(queryChainWrapper.getCompareList(),null,queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList()); + List result = lambdaOperate.getLambdaQueryResult(executeQuery(baseLambdaQuery.getCondition(),baseLambdaQuery.getProjection(),baseLambdaQuery.getSort(),collectionManager.getCollection(clazz),Document.class),clazz); if (result.size() > 1) { throw new MongoQueryException("query result greater than one line"); } return !result.isEmpty() ? result.get(0) : null; } - public T limitOne(List compareConditionList,List projectionList,List basicDBObjectList,List orderList,Class clazz) { - BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(compareConditionList, orderList, projectionList, basicDBObjectList); - List result = lambdaOperate.getLambdaQueryResult(doList(baseLambdaQuery.getCondition(),baseLambdaQuery.getProjection(),baseLambdaQuery.getSort(),collectionManager.getCollection(clazz)),clazz); + public T limitOne(QueryChainWrapper queryChainWrapper,Class clazz) { + BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(queryChainWrapper.getCompareList(),queryChainWrapper.getOrderList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList()); + List result = lambdaOperate.getLambdaQueryResult(executeQuery(baseLambdaQuery.getCondition(),baseLambdaQuery.getProjection(),baseLambdaQuery.getSort(),collectionManager.getCollection(clazz),Document.class),clazz); return !result.isEmpty() ? result.get(0) : null; } - public PageResult page(List compareConditionList, List orderList,List projectionList,List basicDBObjectList, Integer pageNum, Integer pageSize,Class clazz) { + public PageResult page(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize,Class clazz) { + BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(queryChainWrapper.getCompareList(),queryChainWrapper.getOrderList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList()); + FindIterable iterable = executeQuery(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collectionManager.getCollection(clazz),Document.class); + return lambdaOperate.getLambdaQueryResultPage(iterable,count(queryChainWrapper,clazz),new PageParam(pageNum,pageSize),clazz); + } + + public PageResult page(List compareConditionList, List orderList,List projectionList,List basicDBObjectList, Integer pageNum, Integer pageSize, Integer recentPageNum, Class clazz) { BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(compareConditionList, orderList, projectionList, basicDBObjectList); - FindIterable iterable = doList(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collectionManager.getCollection(clazz)); - return lambdaOperate.getLambdaQueryResultPage(iterable,count(compareConditionList,clazz),new PageParam(pageNum,pageSize),clazz); + FindIterable iterable = executeQuery(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collectionManager.getCollection(clazz),Document.class); + return lambdaOperate.getLambdaQueryResultPage(iterable, recentPageCount(compareConditionList,clazz, pageNum, pageSize, recentPageNum),new PageParam(pageNum,pageSize),clazz); } public T getById(Serializable id,Class clazz) { BasicDBObject queryBasic = new BasicDBObject(SqlOperationConstant._ID, new BasicDBObject(SpecialConditionEnum.EQ.getCondition(), ObjectId.isValid(String.valueOf(id)) ? new ObjectId(String.valueOf(id)) : id)); - return DocumentMapperConvert.mapDocument(doGetById(queryBasic,collectionManager.getCollection(clazz)).first(),clazz); + return DocumentMapperConvert.mapDocument(executeQuery(queryBasic,null,null,collectionManager.getCollection(clazz),Document.class).first(),clazz); } public boolean isExist(Serializable id,Class clazz){ BasicDBObject queryBasic = new BasicDBObject(SqlOperationConstant._ID, new BasicDBObject(SpecialConditionEnum.EQ.getCondition(), ObjectId.isValid(String.valueOf(id)) ? new ObjectId(String.valueOf(id)) : id)); - return executeExist(queryBasic, collectionManager.getCollection(clazz)) >= 1; + return executeCount(queryBasic,null, collectionManager.getCollection(clazz)) >= 1; + } + + public boolean isExist(QueryChainWrapper queryChainWrapper,Class clazz){ + BasicDBObject basicDBObject = BuildCondition.buildQueryCondition(queryChainWrapper.getCompareList()); + return executeCount(basicDBObject,null,collectionManager.getCollection(clazz)) >= 1; } public List getByIds(Collection ids,Class clazz) { BasicDBObject basicDBObject = checkIdType(ids); - FindIterable iterable = doGetByIds(basicDBObject, collectionManager.getCollection(clazz)); + FindIterable iterable = executeQuery(basicDBObject,null,null, collectionManager.getCollection(clazz),Document.class); return DocumentMapperConvert.mapDocumentList(iterable, clazz); } - public Boolean update(List compareConditionList,Class clazz) { + public Boolean update(UpdateChainWrapper updateChainWrapper,Class clazz) { + List compareConditionList = new ArrayList<>(); + compareConditionList.addAll(updateChainWrapper.getCompareList()); + compareConditionList.addAll(updateChainWrapper.getUpdateCompareList()); BasicDBObject queryBasic = BuildCondition.buildQueryCondition(compareConditionList); List pushConditionList = compareConditionList.stream().filter(compareCondition -> Objects.equals(compareCondition.getCondition(), SpecialConditionEnum.PUSH.getSubCondition())).collect(Collectors.toList()); List setConditionList = compareConditionList.stream().filter(compareCondition -> Objects.equals(compareCondition.getCondition(), SpecialConditionEnum.SET.getSubCondition())).collect(Collectors.toList()); @@ -271,26 +302,56 @@ public abstract class AbstractExecute implements Execute { return executeUpdate(queryBasic,DocumentUtil.handleBasicDBObject(basicDBObject),collectionManager.getCollection(clazz)).getModifiedCount() >= 1; } - public Boolean remove(List compareConditionList,Class clazz) { - return executeRemove(BuildCondition.buildQueryCondition(compareConditionList),collectionManager.getCollection(clazz)).getDeletedCount() >= 1; + public Boolean remove(UpdateChainWrapper updateChainWrapper, Class clazz) { + return executeRemove(BuildCondition.buildQueryCondition(updateChainWrapper.getCompareList()),collectionManager.getCollection(clazz)).getDeletedCount() >= 1; } - public long count(List compareConditionList,Class clazz){ - return executeCountByCondition(BuildCondition.buildQueryCondition(compareConditionList),collectionManager.getCollection(clazz)); + public long count(QueryChainWrapper queryChainWrapper,Class clazz){ + return executeCount(BuildCondition.buildQueryCondition(queryChainWrapper.getCompareList()),null,collectionManager.getCollection(clazz)); + } + + /** + * 分页查询 查询总条数 + * @param compareConditionList 条件集合 + * @param clazz result class + * @param pageNum 当前页 + * @param pageSize 每页显示行数 + * @param recentPageNum 查询最近n页的数据 {参数=null 表示仅查询当前页数据} {参数取值[5-50] 表示查询最近[5-50]页的数据 建议recentPageNum等于10 参考 百度分页检索} + * @return long + */ + public long recentPageCount(List compareConditionList,Class clazz, Integer pageNum, Integer pageSize, Integer recentPageNum){ + if (recentPageNum == null || !(recentPageNum <= 50 && recentPageNum >= 5)) { + // 返回-1 表示不查询总条数 + return -1L; + } + //分页查询 不查询实际总条数 需要单独查询 是否有数据 + //如果recentPageNum = 10 第1-6页 总页数=10 从第7页开始 需要往后 + 4 页 + int limitParam = (pageNum < (recentPageNum / 2 + 1 + recentPageNum % 2) ? recentPageNum : (pageNum + (recentPageNum / 2 + recentPageNum % 2 - 1))) * pageSize; + CountOptions countOptions = new CountOptions(); + countOptions.skip(limitParam).limit(1); + long isExists = executeCount(BuildCondition.buildQueryCondition(compareConditionList),countOptions, collectionManager.getCollection(clazz)); + //如果查询结果为空 则查询总条数,如果不为空则 limitParam为总条数 + if (isExists == 0) { + // 查询真实总条数 + CountOptions countOptionsReal = new CountOptions(); + countOptionsReal.limit(limitParam); + return executeCount(BuildCondition.buildQueryCondition(compareConditionList),countOptions, collectionManager.getCollection(clazz)); + } + return limitParam; } public long count(Class clazz){ - return doCount(collectionManager.getCollection(clazz)); + return executeCount(null,null,collectionManager.getCollection(clazz)); } public List queryCommand(String command,Class clazz){ - FindIterable iterable = doQueryCommand(BasicDBObject.parse(command), collectionManager.getCollection(clazz)); + FindIterable iterable = executeQuery(BasicDBObject.parse(command),null,null, collectionManager.getCollection(clazz),Document.class); return lambdaOperate.getLambdaQueryResult(iterable,clazz); } public List getByColumn(String column,Object value,Class clazz){ Bson filter = Filters.eq(column, ObjectId.isValid(String.valueOf(value)) ? new ObjectId(String.valueOf(value)) : value); - return DocumentMapperConvert.mapDocumentList(doGetByColumn(filter,collectionManager.getCollection(clazz)),clazz); + return DocumentMapperConvert.mapDocumentList(executeQuery(filter,null,null,collectionManager.getCollection(clazz),Document.class),clazz); } public String createIndex(Bson bson,Class clazz){ @@ -345,6 +406,14 @@ public abstract class AbstractExecute implements Execute { return new BasicDBObject(SqlOperationConstant._ID, new BasicDBObject(SpecialConditionEnum.IN.getCondition(), convertedIds)); } + protected MutablePair getUpdateCondition(List compareConditionList, T entity){ + BasicDBObject queryBasic = BuildCondition.buildQueryCondition(compareConditionList); + Document document = DocumentUtil.checkUpdateField(entity,false); + document.remove(SqlOperationConstant._ID); + BasicDBObject updateField = new BasicDBObject(SpecialConditionEnum.SET.getCondition(), document); + return new MutablePair<>(queryBasic,updateField); + } + protected Document processIdField(T entity,Boolean skip){ Document tableFieldMap = DocumentUtil.checkTableField(entity); fillId(entity, tableFieldMap); @@ -355,21 +424,27 @@ public abstract class AbstractExecute implements Execute { return tableFieldMap; } - protected synchronized Integer getAutoId(Class clazz) { - MongoCollection collection = collectionManager.getCollection("counters"); - Document query = new Document(SqlOperationConstant._ID, collectionNameConvert.convert(clazz)); - Document update = new Document("$inc", new Document(SqlOperationConstant.AUTO_NUM, 1)); - Document document = Optional.ofNullable(MongoTransactionContext.getClientSessionContext()).map(session -> collection.findOneAndUpdate(session,query,update,new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER))).orElseGet(() -> collection.findOneAndUpdate(query,update,new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER))); - if (document == null){ - Integer finalNum = num; - collection.insertOne(new Document(new HashMap(){{ - put(SqlOperationConstant._ID, collectionNameConvert.convert(clazz)); - put(SqlOperationConstant.AUTO_NUM, finalNum); - }})); - }else { - num = Integer.parseInt(String.valueOf(document.get(SqlOperationConstant.AUTO_NUM))); + protected Integer getAutoId(Class clazz) { + String collectionName = collectionNameConvert.convert(clazz); + // 每个Collection单独加锁 + synchronized (collectionName.intern()) { + MongoCollection collection = collectionManager.getCollection("counters"); + Document query = new Document(SqlOperationConstant._ID, collectionName); + Document update = new Document("$inc", new Document(SqlOperationConstant.AUTO_NUM, 1)); + Document document = Optional.ofNullable(MongoTransactionContext.getClientSessionContext()) + .map(session -> collection.findOneAndUpdate(session, query, update, new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER))) + .orElseGet(() -> collection.findOneAndUpdate(query, update, new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER))); + int finalNum = 1; + if (document == null) { + Map map = new HashMap<>(); + map.put(SqlOperationConstant._ID, collectionNameConvert.convert(clazz)); + map.put(SqlOperationConstant.AUTO_NUM, finalNum); + collection.insertOne(new Document(map)); + } else { + finalNum = Integer.parseInt(String.valueOf(document.get(SqlOperationConstant.AUTO_NUM))); + } + return finalNum; } - return num; } protected void fillId(T entity, Document document) { @@ -445,6 +520,10 @@ public abstract class AbstractExecute implements Execute { } protected void aggregateOptions(AggregateIterable aggregateIterable,BasicDBObject optionsBasicDBObject){ + options(aggregateIterable, optionsBasicDBObject); + } + + public static void options(AggregateIterable aggregateIterable, BasicDBObject optionsBasicDBObject) { Set keyedSet = optionsBasicDBObject.keySet(); for (String key : keyedSet) { AggregateOptionsEnum aggregateOptionsEnum = AggregateOptionsEnum.getByOptions(key); diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/execute/Execute.java b/mongo-plus-core/src/main/java/com/anwen/mongo/execute/Execute.java index 59b5ddc79564d8c4bddc51788bfe76f873efb26d..dc0b010ab137527ca7f5b712d0cbfc5ec3aff58d 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/execute/Execute.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/execute/Execute.java @@ -2,16 +2,13 @@ package com.anwen.mongo.execute; import com.anwen.mongo.model.AggregateBasicDBObject; import com.mongodb.BasicDBObject; +import com.mongodb.bulk.BulkWriteResult; import com.mongodb.client.AggregateIterable; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; -import com.mongodb.client.model.CreateIndexOptions; -import com.mongodb.client.model.DropIndexOptions; -import com.mongodb.client.model.IndexModel; -import com.mongodb.client.model.IndexOptions; +import com.mongodb.client.model.*; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.InsertManyResult; -import com.mongodb.client.result.InsertOneResult; import com.mongodb.client.result.UpdateResult; import org.bson.Document; import org.bson.conversions.Bson; @@ -19,53 +16,27 @@ import org.bson.conversions.Bson; import java.util.List; /** - * 抽象的执行器 + * 执行器接口 * * @author JiaChaoYang **/ public interface Execute { - InsertOneResult doSave(Document document, MongoCollection collection); - - InsertManyResult doSaveBatch(List documentList, MongoCollection collection); + InsertManyResult executeSave(List documentList, MongoCollection collection); DeleteResult executeRemove(Bson filter, MongoCollection collection); - FindIterable doList(MongoCollection collection); - - FindIterable doList(MongoCollection collection,Class clazz); - - FindIterable doList(BasicDBObject basicDBObject, BasicDBObject projectionList, BasicDBObject sortCond, MongoCollection collection); - - FindIterable doList(BasicDBObject basicDBObject, BasicDBObject projectionList, BasicDBObject sortCond, MongoCollection collection,Class clazz); - - AggregateIterable doAggregateList(List aggregateConditionList,MongoCollection collection); - - AggregateIterable doAggregateList(List aggregateConditionList,MongoCollection collection,Class clazz); - - FindIterable doGetById(BasicDBObject queryBasic,MongoCollection collection); - - FindIterable doGetByIds(BasicDBObject queryBasic, MongoCollection collection, Class clazz); - - long executeExist(BasicDBObject queryBasic, MongoCollection collection); - - FindIterable doGetByIds(BasicDBObject basicDBObject,MongoCollection collection); - UpdateResult executeUpdate(Bson queryBasic,Bson updateBasic,MongoCollection collection); - DeleteResult executeRemove(BasicDBObject deleteBasic,MongoCollection collection); - - long executeCountByCondition(BasicDBObject basicDBObject,MongoCollection collection); - - long doCount(MongoCollection collection); + FindIterable executeQuery(Bson queryBasic, BasicDBObject projectionList, BasicDBObject sortCond, MongoCollection collection, Class clazz); - FindIterable doQueryCommand(BasicDBObject basicDBObject,MongoCollection collection); + AggregateIterable executeAggregate(List aggregateConditionList, MongoCollection collection, Class clazz); - FindIterable doQueryCommand(BasicDBObject basicDBObject,MongoCollection collection,Class clazz); + long executeCount(BasicDBObject queryBasic,CountOptions countOptions,MongoCollection collection); - FindIterable doGetByColumn(Bson filter,MongoCollection collection); + long estimatedDocumentCount(MongoCollection collection); - FindIterable doGetByColumn(Bson filter,MongoCollection collection,Class clazz); + BulkWriteResult executeBulkWrite(List> writeModelList, MongoCollection collection); String doCreateIndex(Bson bson,MongoCollection collection); diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/execute/ExecutorFactory.java b/mongo-plus-core/src/main/java/com/anwen/mongo/execute/ExecutorFactory.java index 3f8db37442cb721ddfae2e728f9b9279532dc1e1..4af9067de8ba75e7adf85be648c6e77b33f803ac 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/execute/ExecutorFactory.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/execute/ExecutorFactory.java @@ -1,20 +1,17 @@ package com.anwen.mongo.execute; -import com.anwen.mongo.conn.CollectionManager; import com.anwen.mongo.context.MongoTransactionContext; -import com.anwen.mongo.convert.CollectionNameConvert; import com.anwen.mongo.execute.inject.InjectAbstractExecute; import com.anwen.mongo.execute.instance.DefaultExecute; import com.anwen.mongo.execute.instance.SessionExecute; import com.anwen.mongo.manager.MongoPlusClient; -import com.anwen.mongo.model.BaseProperty; -import com.anwen.mongo.toolkit.StringUtils; +import com.anwen.mongo.proxy.ExecutorProxy; import com.mongodb.client.ClientSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Map; -import java.util.Objects; +import java.lang.reflect.Proxy; +import java.util.Optional; /** * 执行器工厂 @@ -26,181 +23,32 @@ public class ExecutorFactory { private final Logger logger = LoggerFactory.getLogger(ExecutorFactory.class); - /** - * 属性配置 - * @author JiaChaoYang - * @date 2023/12/28 10:59 - */ - private BaseProperty baseProperty; - - /** - * 集合名策略 - * @author JiaChaoYang - * @date 2023/12/28 11:44 - */ - private CollectionNameConvert collectionNameConvert; - private MongoPlusClient mongoPlusClient; - /** - * 获取执行器 - * @author JiaChaoYang - * @date 2023/12/28 14:49 - */ - public AbstractExecute getExecute(String database) { - return getExecute(getCollectionManager(database)); - } - - /** - * 获取执行器 - * @author JiaChaoYang - * @date 2024/1/20 23:32 - */ - public Execute getExecuteInterface(String database){ - return getExecute(getCollectionManager(database)); - } - - public AbstractExecute getExecute(CollectionManager collectionManager){ - ClientSession clientSessionContext = MongoTransactionContext.getClientSessionContext(); - if (clientSessionContext != null) { - return new SessionExecute(collectionNameConvert,collectionManager,clientSessionContext); - } - return new DefaultExecute(collectionNameConvert,collectionManager); - } - - public InjectAbstractExecute getInjectExecute(String database){ - CollectionManager collectionManager = getCollectionManager(database); - return new InjectAbstractExecute(collectionManager,getExecute(collectionManager)); - } - - public CollectionManager getCollectionManager(String database){ - Map managerMap = mongoPlusClient.getCollectionManager(); - if (StringUtils.isBlank(database)){ - database = managerMap.keySet().stream().findFirst().get(); - } - CollectionManager collectionManager = managerMap.get(database); - if (null == collectionManager){ - collectionManager = new CollectionManager(mongoPlusClient.getMongoClient(), collectionNameConvert, database); - mongoPlusClient.getMongoDatabase().add(mongoPlusClient.getMongoClient().getDatabase(database)); - mongoPlusClient.getCollectionManager().put(database,collectionManager); - } - return collectionManager; - } - -// /** -// * 获取自定义执行器 -// * @param clazz 执行器class -// * @param expandParam 拓展参数 -// * @return com.anwen.mongo.execute.Execute -// * @author JiaChaoYang -// * @date 2023/12/28 16:03 -// */ -// public AbstractExecute getExecute(Class clazz, Map expandParam){ -// Constructor constructor; -// try { -// constructor = clazz.getConstructor(CollectionNameConvert.class,CollectionManager.class,Map.class); -// } catch (NoSuchMethodException e) { -// logger.error("In the class of an extended executor, there must be a constructor with the following parameters: ‘MongoClient MongoClient, BaseProperty BaseProperty, CollectionNameConvert CollectionNameConvert, CollectionManager CollectionManager, MapexpandExecuteMap’"); -// throw new RuntimeException(e); -// } -// try { -// return (AbstractExecute) constructor.newInstance(collectionNameConvert,collectionManagerMap.get(),expandParam); -// } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { -// logger.error("Instance creation failed, exception reason: {}",e.getMessage()); -// throw new RuntimeException(e); -// } -// } - - public static ExecuteFactoryBuilder builder() { - return new ExecuteFactoryBuilder(); - } - - public BaseProperty getBaseProperty() { - return this.baseProperty; - } - - public CollectionNameConvert getCollectionNameConvert() { - return this.collectionNameConvert; - } - - public void setBaseProperty(BaseProperty baseProperty) { - this.baseProperty = baseProperty; - } - - public void setCollectionNameConvert(CollectionNameConvert collectionNameConvert) { - this.collectionNameConvert = collectionNameConvert; + public ExecutorFactory() { } - public void setMongoPlusClient(MongoPlusClient mongoPlusClient){ + public ExecutorFactory(MongoPlusClient mongoPlusClient){ this.mongoPlusClient = mongoPlusClient; } - public MongoPlusClient getMongoPlusClient(){ - return this.mongoPlusClient; - } - - protected boolean canEqual(Object other) { - return other instanceof ExecutorFactory; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ExecutorFactory)) return false; - ExecutorFactory that = (ExecutorFactory) o; - return Objects.equals(logger, that.logger) && Objects.equals(getBaseProperty(), that.getBaseProperty()) && Objects.equals(getCollectionNameConvert(), that.getCollectionNameConvert()) && Objects.equals(getMongoPlusClient(), that.getMongoPlusClient()); - } - - @Override - public int hashCode() { - return Objects.hash(logger, getBaseProperty(), getCollectionNameConvert(), getMongoPlusClient()); - } - - @Override - public String toString() { - return "ExecutorFactory{" + - "baseProperty=" + baseProperty + - ", collectionNameConvert=" + collectionNameConvert + - ", mongoPlusClient=" + mongoPlusClient + - '}'; - } - - public ExecutorFactory(BaseProperty baseProperty, CollectionNameConvert collectionNameConvert, MongoPlusClient mongoPlusClient) { - this.baseProperty = baseProperty; - this.collectionNameConvert = collectionNameConvert; - this.mongoPlusClient = mongoPlusClient; - } + public Execute getExecute(){ + ClientSession clientSessionContext = MongoTransactionContext.getClientSessionContext(); + Execute execute = Optional.ofNullable(clientSessionContext) + .map(clientSession -> (Execute) new SessionExecute(clientSession)) + .orElseGet(DefaultExecute::new); + Class clazz = execute.getClass(); + return (Execute) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),new ExecutorProxy(execute)); - public ExecutorFactory() { } - public static class ExecuteFactoryBuilder { - private BaseProperty baseProperty; - private CollectionNameConvert collectionNameConvert; - - private MongoPlusClient mongoPlusClient; - - ExecuteFactoryBuilder() { - } - - public ExecuteFactoryBuilder baseProperty(BaseProperty baseProperty) { - this.baseProperty = baseProperty; - return this; - } - - public ExecuteFactoryBuilder collectionNameConvert(CollectionNameConvert collectionNameConvert) { - this.collectionNameConvert = collectionNameConvert; - return this; - } - - public ExecuteFactoryBuilder mongoPlusClient(MongoPlusClient mongoPlusClient){ - this.mongoPlusClient = mongoPlusClient; - return this; - } - - public ExecutorFactory build() { - return new ExecutorFactory(this.baseProperty, this.collectionNameConvert, mongoPlusClient); - } + public InjectAbstractExecute getInjectExecute(String database){ + ClientSession clientSessionContext = MongoTransactionContext.getClientSessionContext(); + Execute execute = Optional.ofNullable(clientSessionContext) + .map(clientSession -> (Execute) new SessionExecute(clientSession)) + .orElseGet(DefaultExecute::new); + Class clazz = execute.getClass(); + return new InjectAbstractExecute(mongoPlusClient.getCollectionManager(database), (Execute) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),new ExecutorProxy(execute))); } } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/execute/inject/InjectAbstractExecute.java b/mongo-plus-core/src/main/java/com/anwen/mongo/execute/inject/InjectAbstractExecute.java index f76abad78ae5e9db138bd81ba947b680b380229f..fed45565a00e0dd4dab34ee552feff7bb36f109c 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/execute/inject/InjectAbstractExecute.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/execute/inject/InjectAbstractExecute.java @@ -4,13 +4,14 @@ import com.anwen.mongo.conditions.BuildCondition; import com.anwen.mongo.conditions.interfaces.aggregate.pipeline.Projection; import com.anwen.mongo.conditions.interfaces.condition.CompareCondition; import com.anwen.mongo.conditions.interfaces.condition.Order; +import com.anwen.mongo.conditions.query.QueryChainWrapper; import com.anwen.mongo.conn.CollectionManager; import com.anwen.mongo.constant.SqlOperationConstant; import com.anwen.mongo.convert.Converter; import com.anwen.mongo.convert.DocumentMapperConvert; import com.anwen.mongo.domain.MongoQueryException; -import com.anwen.mongo.enums.AggregateOptionsEnum; import com.anwen.mongo.enums.SpecialConditionEnum; +import com.anwen.mongo.execute.AbstractExecute; import com.anwen.mongo.execute.Execute; import com.anwen.mongo.model.*; import com.anwen.mongo.toolkit.*; @@ -27,7 +28,6 @@ import org.slf4j.LoggerFactory; import java.io.Serializable; import java.util.*; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -52,7 +52,8 @@ public class InjectAbstractExecute { public Boolean save(String collectionName, Map entityMap) { try { - return execute.doSave(DocumentUtil.handleMap(entityMap,true),collectionManager.getCollection(collectionName)).wasAcknowledged(); +// return execute.executeSave(Collections.singletonList(DocumentUtil.handleMap(entityMap, true)),collectionManager.getCollection(collectionName)).wasAcknowledged(); + return true; } catch (Exception e) { logger.error("save fail , error info : {}", e.getMessage(), e); return false; @@ -62,7 +63,8 @@ public class InjectAbstractExecute { public Boolean saveBatch(String collectionName, Collection> entityList) { try { List documentList = DocumentUtil.handleMapList(entityList,true); - return execute.doSaveBatch(documentList, collectionManager.getCollection(collectionName)).getInsertedIds().size() == entityList.size(); +// return execute.executeSave(documentList, collectionManager.getCollection(collectionName)).getInsertedIds().size() == entityList.size(); + return true; } catch (Exception e) { logger.error("saveBatch fail , error info : {}", e.getMessage(), e); return false; @@ -154,24 +156,24 @@ public class InjectAbstractExecute { } public List> list(String collectionName) { - return Converter.convertDocumentToMap(execute.doList(collectionManager.getCollection(collectionName), Map.class)); + return Converter.convertDocumentToMap(execute.executeQuery(null,null,null,collectionManager.getCollection(collectionName), Map.class)); } public List> list(String collectionName, List compareConditionList, List orderList, List projectionList, List basicDBObjectList) { BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(compareConditionList, orderList, projectionList, basicDBObjectList); - FindIterable mapFindIterable = execute.doList(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collectionManager.getCollection(collectionName), Map.class); + FindIterable mapFindIterable = execute.executeQuery(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collectionManager.getCollection(collectionName), Map.class); return Converter.convertDocumentToMap(mapFindIterable); } public PageResult> page(String collectionName, List compareConditionList, List orderList, List projectionList, List basicDBObjectList, Integer pageNum, Integer pageSize) { BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(compareConditionList, orderList, projectionList, basicDBObjectList); - FindIterable mapFindIterable = execute.doList(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collectionManager.getCollection(collectionName), Map.class); + FindIterable mapFindIterable = execute.executeQuery(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collectionManager.getCollection(collectionName), Map.class); return lambdaOperate.getLambdaQueryResultPage(mapFindIterable,count(collectionName,compareConditionList),new PageParam(pageNum,pageSize)); } public Map one(String collectionName, List compareConditionList,List projectionList,List basicDBObjectList) { BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(compareConditionList, null, projectionList, basicDBObjectList); - List> result = Converter.convertDocumentToMap(execute.doList(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collectionManager.getCollection(collectionName), Map.class)); + List> result = Converter.convertDocumentToMap(execute.executeQuery(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collectionManager.getCollection(collectionName), Map.class)); if (result.size() > 1) { throw new MongoQueryException("query result greater than one line"); } @@ -180,28 +182,33 @@ public class InjectAbstractExecute { public Map limitOne(String collectionName, List compareConditionList,List projectionList,List basicDBObjectList,List orderList) { BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(compareConditionList, null, projectionList, basicDBObjectList); - List> result = Converter.convertDocumentToMap(execute.doList(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collectionManager.getCollection(collectionName), Map.class)); + List> result = Converter.convertDocumentToMap(execute.executeQuery(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collectionManager.getCollection(collectionName), Map.class)); return !result.isEmpty() ? result.get(0) : new HashMap<>(); } public boolean isExist(String collectionName, Serializable id){ BasicDBObject queryBasic = new BasicDBObject(SqlOperationConstant._ID, new BasicDBObject(SpecialConditionEnum.EQ.getCondition(), ObjectId.isValid(String.valueOf(id)) ? new ObjectId(String.valueOf(id)) : id)); - return execute.executeExist(queryBasic,collectionManager.getCollection(collectionName)) >= 1; + return execute.executeCount(queryBasic,null,collectionManager.getCollection(collectionName)) >= 1; + } + + public boolean isExist(String collectionName,QueryChainWrapper queryChainWrapper){ + BasicDBObject basicDBObject = BuildCondition.buildQueryCondition(queryChainWrapper.getCompareList()); + return execute.executeCount(basicDBObject,null,collectionManager.getCollection(collectionName)) >= 1; } public List> getByColumn(String collectionName,String column,Object value){ Bson filter = Filters.eq(column, ObjectId.isValid(String.valueOf(value)) ? new ObjectId(String.valueOf(value)) : value); - return Converter.convertDocumentToMap(execute.doGetByColumn(filter,collectionManager.getCollection(collectionName),Map.class)); + return Converter.convertDocumentToMap(execute.executeQuery(filter,null,null,collectionManager.getCollection(collectionName),Map.class)); } public Map getById(String collectionName,Serializable id) { BasicDBObject queryBasic = new BasicDBObject(SqlOperationConstant._ID, new BasicDBObject(SpecialConditionEnum.EQ.getCondition(), ObjectId.isValid(String.valueOf(id)) ? new ObjectId(String.valueOf(id)) : id)); - return execute.doGetById(queryBasic,collectionManager.getCollection(collectionName)).first(); + return execute.executeQuery(queryBasic,null,null,collectionManager.getCollection(collectionName),Map.class).first(); } public List> getByIds(String collectionName,Collection ids) { BasicDBObject basicDBObject = checkIdType(ids); - FindIterable iterable = execute.doGetByIds(basicDBObject, collectionManager.getCollection(collectionName),Map.class); + FindIterable iterable = execute.executeQuery(basicDBObject,null,null, collectionManager.getCollection(collectionName),Map.class); return Converter.convertDocumentToMap(iterable); } @@ -214,7 +221,7 @@ public class InjectAbstractExecute { public List> queryCommand(String collectionName,String sql){ BasicDBObject basicDBObject = BasicDBObject.parse(sql); - return Converter.convertDocumentToMap(execute.doQueryCommand(basicDBObject,collectionManager.getCollection(collectionName),Map.class)); + return Converter.convertDocumentToMap(execute.executeQuery(basicDBObject,null,null,collectionManager.getCollection(collectionName),Map.class)); } public Boolean update(String collectionName,List compareConditionList){ @@ -237,7 +244,7 @@ public class InjectAbstractExecute { } public long count(String collectionName,List compareConditionList){ - return execute.executeCountByCondition(BuildCondition.buildQueryCondition(compareConditionList),collectionManager.getCollection(collectionName)); + return execute.executeCount(BuildCondition.buildQueryCondition(compareConditionList),null,collectionManager.getCollection(collectionName)); } public List> aggregateList(String collectionName, List aggregateList, List basicDBObjectList, BasicDBObject optionsBasicDBObject){ @@ -246,7 +253,7 @@ public class InjectAbstractExecute { addAll(basicDBObjectList); }}; aggregateConditionList.sort(Comparator.comparingInt(AggregateBasicDBObject::getOrder)); - AggregateIterable aggregateIterable = execute.doAggregateList(aggregateConditionList, collectionManager.getCollection(collectionName), Map.class); + AggregateIterable aggregateIterable = execute.executeAggregate(aggregateConditionList, collectionManager.getCollection(collectionName), Map.class); aggregateOptions(aggregateIterable,optionsBasicDBObject); return Converter.convertDocumentToMap(aggregateIterable.iterator()); } @@ -257,13 +264,13 @@ public class InjectAbstractExecute { addAll(basicDBObjectList); }}; aggregateConditionList.sort(Comparator.comparingInt(AggregateBasicDBObject::getOrder)); - AggregateIterable aggregateIterable = execute.doAggregateList(aggregateConditionList, collectionManager.getCollection(collectionName)); + AggregateIterable aggregateIterable = execute.executeAggregate(aggregateConditionList, collectionManager.getCollection(collectionName),Document.class); aggregateOptions(aggregateIterable,optionsBasicDBObject); return DocumentMapperConvert.mapDocumentList(aggregateIterable.iterator(),clazz); } public long count(String collectionName){ - return execute.doCount(collectionManager.getCollection(collectionName)); + return execute.executeCount(null,null,collectionManager.getCollection(collectionName)); } public String createIndex(String collectionName,Bson bson){ @@ -312,42 +319,7 @@ public class InjectAbstractExecute { } protected void aggregateOptions(AggregateIterable aggregateIterable,BasicDBObject optionsBasicDBObject){ - Set keyedSet = optionsBasicDBObject.keySet(); - for (String key : keyedSet) { - AggregateOptionsEnum aggregateOptionsEnum = AggregateOptionsEnum.getByOptions(key); - switch (Objects.requireNonNull(aggregateOptionsEnum)){ - case ALLOW_DISK_USE: - aggregateIterable.allowDiskUse(optionsBasicDBObject.getBoolean(key)); - break; - case COLLATION: - aggregateIterable.collation((Collation) optionsBasicDBObject.get(key)); - break; - case BATCH_SIZE: - aggregateIterable.batchSize(optionsBasicDBObject.getInt(key)); - break; - case MAX_TIME_MS: - aggregateIterable.maxTime(optionsBasicDBObject.getLong(key), TimeUnit.MILLISECONDS); - break; - case MAX_AWAIT_TIME_MS: - aggregateIterable.maxAwaitTime(optionsBasicDBObject.getLong(key),TimeUnit.MILLISECONDS); - break; - case BYPASS_DOCUMENT_VALIDATION: - aggregateIterable.bypassDocumentValidation(optionsBasicDBObject.getBoolean(key)); - break; - case COMMENT: - aggregateIterable.comment(String.valueOf(optionsBasicDBObject.get(key))); - break; - case COMMENT_STR: - aggregateIterable.comment(optionsBasicDBObject.getString(key)); - break; - case HINT: - aggregateIterable.hint((Bson) optionsBasicDBObject.get(key)); - break; - case LET: - aggregateIterable.let((Bson) optionsBasicDBObject.get(key)); - break; - } - } + AbstractExecute.options(aggregateIterable, optionsBasicDBObject); } } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/execute/instance/DefaultExecute.java b/mongo-plus-core/src/main/java/com/anwen/mongo/execute/instance/DefaultExecute.java index 4895702fd848708bbfd4ccb1dbed0e7e9e893a9c..b117299c5a1d90d2f5a5bfbde5ed702ae3937d0e 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/execute/instance/DefaultExecute.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/execute/instance/DefaultExecute.java @@ -1,26 +1,22 @@ package com.anwen.mongo.execute.instance; -import com.anwen.mongo.conn.CollectionManager; -import com.anwen.mongo.convert.CollectionNameConvert; import com.anwen.mongo.convert.DocumentMapperConvert; -import com.anwen.mongo.execute.AbstractExecute; +import com.anwen.mongo.execute.Execute; import com.anwen.mongo.model.AggregateBasicDBObject; import com.mongodb.BasicDBObject; +import com.mongodb.bulk.BulkWriteResult; import com.mongodb.client.AggregateIterable; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; -import com.mongodb.client.model.CreateIndexOptions; -import com.mongodb.client.model.DropIndexOptions; -import com.mongodb.client.model.IndexModel; -import com.mongodb.client.model.IndexOptions; +import com.mongodb.client.model.*; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.InsertManyResult; -import com.mongodb.client.result.InsertOneResult; import com.mongodb.client.result.UpdateResult; import org.bson.Document; import org.bson.conversions.Bson; import java.util.List; +import java.util.Optional; /** * 默认执行器实例 @@ -29,21 +25,16 @@ import java.util.List; * @project mongo-plus * @date 2023-12-28 11:03 **/ -public class DefaultExecute extends AbstractExecute { - - - public DefaultExecute(CollectionNameConvert collectionNameConvert, CollectionManager collectionManager) { - super(collectionNameConvert, collectionManager); - } +public class DefaultExecute implements Execute { @Override - public InsertOneResult doSave(Document document, MongoCollection collection) { - return collection.insertOne(document); + public InsertManyResult executeSave(List documentList, MongoCollection collection) { + return collection.insertMany(documentList); } @Override - public InsertManyResult doSaveBatch(List documentList, MongoCollection collection) { - return collection.insertMany(documentList); + public BulkWriteResult executeBulkWrite(List> writeModelList, MongoCollection collection) { + return collection.bulkWrite(writeModelList); } @Override @@ -52,53 +43,27 @@ public class DefaultExecute extends AbstractExecute { } @Override - public FindIterable doList(MongoCollection collection) { - return collection.find(); - } - - @Override - public FindIterable doList(MongoCollection collection, Class clazz) { - return collection.find(clazz); - } - - @Override - public FindIterable doList(BasicDBObject basicDBObject, BasicDBObject projectionList, BasicDBObject sortCond, MongoCollection collection) { - return collection.find(basicDBObject).projection(projectionList).sort(sortCond); + public FindIterable executeQuery(Bson queryBasic, BasicDBObject projectionList, BasicDBObject sortCond, MongoCollection collection, Class clazz) { + return Optional.ofNullable(queryBasic) + .map(qb -> collection.find(qb,clazz)) + .orElseGet(() -> collection.find(clazz)) + .projection(projectionList) + .sort(sortCond); } @Override - public FindIterable doList(BasicDBObject basicDBObject, BasicDBObject projectionList, BasicDBObject sortCond, MongoCollection collection, Class clazz) { - return collection.find(basicDBObject,clazz).projection(projectionList).sort(sortCond); - } - - @Override - public AggregateIterable doAggregateList(List aggregateConditionList, MongoCollection collection) { - return collection.aggregate(aggregateConditionList); - } - - @Override - public AggregateIterable doAggregateList(List aggregateConditionList, MongoCollection collection, Class clazz) { + public AggregateIterable executeAggregate(List aggregateConditionList, MongoCollection collection, Class clazz) { return collection.aggregate(aggregateConditionList, clazz); } @Override - public FindIterable doGetById(BasicDBObject queryBasic, MongoCollection collection) { - return collection.find(queryBasic); - } - - @Override - public FindIterable doGetByIds(BasicDBObject queryBasic, MongoCollection collection, Class clazz) { - return collection.find(queryBasic,clazz); - } - - @Override - public long executeExist(BasicDBObject queryBasic, MongoCollection collection) { - return collection.countDocuments(queryBasic); + public long executeCount(BasicDBObject queryBasic, CountOptions countOptions, MongoCollection collection) { + return Optional.ofNullable(countOptions).map(co -> collection.countDocuments(queryBasic,co)).orElseGet(() -> collection.countDocuments(queryBasic)); } @Override - public FindIterable doGetByIds(BasicDBObject basicDBObject, MongoCollection collection) { - return collection.find(basicDBObject); + public long estimatedDocumentCount(MongoCollection collection) { + return collection.estimatedDocumentCount(); } @Override @@ -106,41 +71,6 @@ public class DefaultExecute extends AbstractExecute { return collection.updateMany(queryBasic,updateBasic); } - @Override - public DeleteResult executeRemove(BasicDBObject deleteBasic, MongoCollection collection) { - return collection.deleteMany(deleteBasic); - } - - @Override - public long executeCountByCondition(BasicDBObject basicDBObject, MongoCollection collection) { - return collection.countDocuments(basicDBObject); - } - - @Override - public long doCount(MongoCollection collection) { - return collection.countDocuments(); - } - - @Override - public FindIterable doQueryCommand(BasicDBObject basicDBObject, MongoCollection collection) { - return collection.find(basicDBObject); - } - - @Override - public FindIterable doQueryCommand(BasicDBObject basicDBObject, MongoCollection collection, Class clazz) { - return collection.find(basicDBObject,clazz); - } - - @Override - public FindIterable doGetByColumn(Bson filter, MongoCollection collection) { - return collection.find(filter); - } - - @Override - public FindIterable doGetByColumn(Bson filter, MongoCollection collection, Class clazz) { - return collection.find(filter,clazz); - } - @Override public String doCreateIndex(Bson bson, MongoCollection collection) { return collection.createIndex(bson); diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/execute/instance/SessionExecute.java b/mongo-plus-core/src/main/java/com/anwen/mongo/execute/instance/SessionExecute.java index becae3f1ede8019fd7ad5a663e3a3b0c7a69c2a5..f75e2b18b293a8249a87d90a2826bf41cc9d0aea 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/execute/instance/SessionExecute.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/execute/instance/SessionExecute.java @@ -1,27 +1,23 @@ package com.anwen.mongo.execute.instance; -import com.anwen.mongo.conn.CollectionManager; -import com.anwen.mongo.convert.CollectionNameConvert; import com.anwen.mongo.convert.DocumentMapperConvert; -import com.anwen.mongo.execute.AbstractExecute; +import com.anwen.mongo.execute.Execute; import com.anwen.mongo.model.AggregateBasicDBObject; import com.mongodb.BasicDBObject; +import com.mongodb.bulk.BulkWriteResult; import com.mongodb.client.AggregateIterable; import com.mongodb.client.ClientSession; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; -import com.mongodb.client.model.CreateIndexOptions; -import com.mongodb.client.model.DropIndexOptions; -import com.mongodb.client.model.IndexModel; -import com.mongodb.client.model.IndexOptions; +import com.mongodb.client.model.*; import com.mongodb.client.result.DeleteResult; import com.mongodb.client.result.InsertManyResult; -import com.mongodb.client.result.InsertOneResult; import com.mongodb.client.result.UpdateResult; import org.bson.Document; import org.bson.conversions.Bson; import java.util.List; +import java.util.Optional; /** * session实例 @@ -30,23 +26,22 @@ import java.util.List; * @project mongo-plus * @date 2023-12-28 11:03 **/ -public class SessionExecute extends AbstractExecute { +public class SessionExecute implements Execute { private final ClientSession clientSession; - public SessionExecute(CollectionNameConvert collectionNameConvert, CollectionManager collectionManager, ClientSession clientSession) { - super(collectionNameConvert, collectionManager); + public SessionExecute(ClientSession clientSession) { this.clientSession = clientSession; } @Override - public InsertOneResult doSave(Document document, MongoCollection collection) { - return collection.insertOne(clientSession,document); + public InsertManyResult executeSave(List documentList, MongoCollection collection) { + return collection.insertMany(clientSession,documentList); } @Override - public InsertManyResult doSaveBatch(List documentList, MongoCollection collection) { - return collection.insertMany(clientSession,documentList); + public BulkWriteResult executeBulkWrite(List> writeModelList, MongoCollection collection) { + return collection.bulkWrite(clientSession,writeModelList); } @Override @@ -55,52 +50,27 @@ public class SessionExecute extends AbstractExecute { } @Override - public FindIterable doList(MongoCollection collection) { - return collection.find(clientSession); - } - - @Override - public FindIterable doList(MongoCollection collection, Class clazz) { - return collection.find(clientSession,clazz); - } - - @Override - public FindIterable doList(BasicDBObject basicDBObject, BasicDBObject projectionList, BasicDBObject sortCond, MongoCollection collection) { - return collection.find(clientSession,basicDBObject).projection(projectionList).sort(sortCond); - } - - @Override - public FindIterable doList(BasicDBObject basicDBObject, BasicDBObject projectionList, BasicDBObject sortCond, MongoCollection collection, Class clazz) { - return collection.find(clientSession,basicDBObject,clazz).projection(projectionList).sort(sortCond); + public FindIterable executeQuery(Bson queryBasic, BasicDBObject projectionList, BasicDBObject sortCond, MongoCollection collection, Class clazz) { + return Optional.ofNullable(queryBasic) + .map(qb -> collection.find(clientSession,qb,clazz)) + .orElseGet(() -> collection.find(clientSession,clazz)) + .projection(projectionList) + .sort(sortCond); } @Override - public AggregateIterable doAggregateList(List aggregateConditionList, MongoCollection collection) { - return collection.aggregate(clientSession,aggregateConditionList); - } - - @Override - public AggregateIterable doAggregateList(List aggregateConditionList, MongoCollection collection, Class clazz) { + public AggregateIterable executeAggregate(List aggregateConditionList, MongoCollection collection, Class clazz) { return collection.aggregate(clientSession,aggregateConditionList, clazz); } - @Override - public FindIterable doGetById(BasicDBObject queryBasic, MongoCollection collection) { - return collection.find(clientSession,queryBasic); - } @Override - public FindIterable doGetByIds(BasicDBObject queryBasic, MongoCollection collection, Class clazz) { - return collection.find(queryBasic,clazz); + public long executeCount(BasicDBObject queryBasic, CountOptions countOptions, MongoCollection collection) { + return Optional.ofNullable(countOptions).map(co -> collection.countDocuments(clientSession, queryBasic,co)).orElseGet(() -> collection.countDocuments(clientSession, queryBasic)); } @Override - public long executeExist(BasicDBObject queryBasic, MongoCollection collection) { - return collection.countDocuments(clientSession,queryBasic); - } - - @Override - public FindIterable doGetByIds(BasicDBObject basicDBObject, MongoCollection collection) { - return collection.find(clientSession,basicDBObject); + public long estimatedDocumentCount(MongoCollection collection) { + return collection.countDocuments(); } @Override @@ -108,41 +78,6 @@ public class SessionExecute extends AbstractExecute { return collection.updateMany(clientSession,queryBasic,updateBasic); } - @Override - public DeleteResult executeRemove(BasicDBObject deleteBasic, MongoCollection collection) { - return collection.deleteMany(clientSession,deleteBasic); - } - - @Override - public long executeCountByCondition(BasicDBObject basicDBObject, MongoCollection collection) { - return collection.countDocuments(clientSession,basicDBObject); - } - - @Override - public long doCount(MongoCollection collection) { - return collection.countDocuments(clientSession); - } - - @Override - public FindIterable doQueryCommand(BasicDBObject basicDBObject, MongoCollection collection) { - return collection.find(clientSession,basicDBObject); - } - - @Override - public FindIterable doQueryCommand(BasicDBObject basicDBObject, MongoCollection collection, Class clazz) { - return collection.find(clientSession,basicDBObject,clazz); - } - - @Override - public FindIterable doGetByColumn(Bson filter, MongoCollection collection) { - return collection.find(clientSession,filter); - } - - @Override - public FindIterable doGetByColumn(Bson filter, MongoCollection collection, Class clazz) { - return collection.find(clientSession,filter,clazz); - } - @Override public String doCreateIndex(Bson bson, MongoCollection collection) { return collection.createIndex(clientSession,bson); diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/Interceptor.java b/mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/Interceptor.java index 6c63ea2c1a0908aba964c1fffc8030dabd3bf258..3738d97aadf1079d4fb7bcafdde8e2b6baa7bf00 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/Interceptor.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/Interceptor.java @@ -1,59 +1,56 @@ package com.anwen.mongo.interceptor; -import com.anwen.mongo.model.command.CommandFailed; -import com.anwen.mongo.model.command.CommandStarted; -import com.anwen.mongo.model.command.CommandSucceeded; +import com.anwen.mongo.model.AggregateBasicDBObject; +import com.anwen.mongo.model.MutablePair; +import com.anwen.mongo.model.QueryParam; +import com.mongodb.BasicDBObject; +import com.mongodb.client.model.CountOptions; +import com.mongodb.client.model.WriteModel; +import org.bson.Document; +import org.bson.conversions.Bson; + +import java.util.List; /** + * 拦截器,代理{@link com.anwen.mongo.execute.Execute}接口,增删改查会经过 + * * @author JiaChaoYang - * @project mongo-plus - * @description 拦截器,实际上是通过mongo的命令监听器实现,MongoDB团队并不推荐这么做 - * @date 2023-11-22 14:12 **/ public interface Interceptor { /** - * 最高优先级 - * @see java.lang.Integer#MIN_VALUE - */ - int HIGHEST_PRECEDENCE = Integer.MIN_VALUE; - - /** - * 最低优先级 - * @see java.lang.Integer#MAX_VALUE - */ - int LOWEST_PRECEDENCE = Integer.MAX_VALUE; - - /** - * 处理命令开始信息 - * @param commandStarted 命令执行开始信息对象 + * 添加拦截方法 + * @param documentList 经过添加方法的值 + * @return java.util.List * @author JiaChaoYang - * @date 2023/11/22 14:34 + * @date 2024/3/17 0:37 */ - void commandStarted(CommandStarted commandStarted); + default List executeSave(List documentList){ + return documentList; + }; - /** - * 处理命令成功信息 - * @param commandSucceeded 命令成功信息对象 - * @author JiaChaoYang - * @date 2023/11/22 14:35 - */ - void commandSucceeded(CommandSucceeded commandSucceeded); + default Bson executeRemove(Bson filter){ + return filter; + } - /** - * 处理命令失败信息 - * @param commandFailed 处理命令失败信息对象 - * @author JiaChaoYang - * @date 2023/11/22 14:35 - */ - void commandFailed(CommandFailed commandFailed); + default MutablePair executeUpdate(Bson queryBasic, Bson updateBasic){ + return new MutablePair<>(queryBasic, updateBasic); + } - /** - * 指定拦截器排序 - * @return int - * @author JiaChaoYang - * @date 2023/11/22 16:27 - */ - int getOrder(); + default QueryParam executeQuery(Bson queryBasic, BasicDBObject projectionList, BasicDBObject sortCond){ + return new QueryParam(queryBasic, projectionList, sortCond); + } + + default List executeAggregate(List aggregateConditionList){ + return aggregateConditionList; + } + + default MutablePair executeCount(BasicDBObject queryBasic, CountOptions countOptions){ + return new MutablePair<>(queryBasic, countOptions); + } + + default List> executeBulkWrite(List> writeModelList){ + return writeModelList; + } } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/BaseInterceptor.java b/mongo-plus-core/src/main/java/com/anwen/mongo/listener/BaseListener.java similarity index 85% rename from mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/BaseInterceptor.java rename to mongo-plus-core/src/main/java/com/anwen/mongo/listener/BaseListener.java index f34cac3d46051995a00accfa3caf243d1268f8ee..1f4ffa4248009041f77ccb8723a8f542bc0f2499 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/BaseInterceptor.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/listener/BaseListener.java @@ -1,4 +1,4 @@ -package com.anwen.mongo.interceptor; +package com.anwen.mongo.listener; import com.anwen.mongo.domain.MongoPlusInterceptorException; import com.anwen.mongo.model.command.CommandFailed; @@ -11,11 +11,11 @@ import com.mongodb.event.CommandSucceededEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class BaseInterceptor implements CommandListener { +public class BaseListener implements CommandListener { - private final MongoPlusInterceptor mongoPlusInterceptor = new MongoPlusInterceptor(); + private final MongoPlusListener mongoPlusInterceptor = new MongoPlusListener(); - private final Logger logger = LoggerFactory.getLogger(BaseInterceptor.class); + private final Logger logger = LoggerFactory.getLogger(BaseListener.class); @Override public void commandStarted(CommandStartedEvent event) { diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/listener/Listener.java b/mongo-plus-core/src/main/java/com/anwen/mongo/listener/Listener.java new file mode 100644 index 0000000000000000000000000000000000000000..308b3adb64014e222f3ed8659bc31ebc7acedb6f --- /dev/null +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/listener/Listener.java @@ -0,0 +1,59 @@ +package com.anwen.mongo.listener; + +import com.anwen.mongo.model.command.CommandFailed; +import com.anwen.mongo.model.command.CommandStarted; +import com.anwen.mongo.model.command.CommandSucceeded; + +/** + * @author JiaChaoYang + * @project mongo-plus + * @description 拦截器,实际上是通过mongo的命令监听器实现,MongoDB团队并不推荐这么做 + * @date 2023-11-22 14:12 + **/ +public interface Listener { + + /** + * 最高优先级 + * @see java.lang.Integer#MIN_VALUE + */ + int HIGHEST_PRECEDENCE = Integer.MIN_VALUE; + + /** + * 最低优先级 + * @see java.lang.Integer#MAX_VALUE + */ + int LOWEST_PRECEDENCE = Integer.MAX_VALUE; + + /** + * 处理命令开始信息 + * @param commandStarted 命令执行开始信息对象 + * @author JiaChaoYang + * @date 2023/11/22 14:34 + */ + void commandStarted(CommandStarted commandStarted); + + /** + * 处理命令成功信息 + * @param commandSucceeded 命令成功信息对象 + * @author JiaChaoYang + * @date 2023/11/22 14:35 + */ + void commandSucceeded(CommandSucceeded commandSucceeded); + + /** + * 处理命令失败信息 + * @param commandFailed 处理命令失败信息对象 + * @author JiaChaoYang + * @date 2023/11/22 14:35 + */ + void commandFailed(CommandFailed commandFailed); + + /** + * 指定拦截器排序 + * @return int + * @author JiaChaoYang + * @date 2023/11/22 16:27 + */ + int getOrder(); + +} diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/MongoPlusInterceptor.java b/mongo-plus-core/src/main/java/com/anwen/mongo/listener/MongoPlusListener.java similarity index 56% rename from mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/MongoPlusInterceptor.java rename to mongo-plus-core/src/main/java/com/anwen/mongo/listener/MongoPlusListener.java index c687939d4426e793ede009d14ef97a1ee9601946..f89bac23111656371bdd98c012d83e293e521a22 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/MongoPlusInterceptor.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/listener/MongoPlusListener.java @@ -1,6 +1,6 @@ -package com.anwen.mongo.interceptor; +package com.anwen.mongo.listener; -import com.anwen.mongo.cache.global.InterceptorCache; +import com.anwen.mongo.cache.global.ListenerCache; import com.anwen.mongo.model.command.CommandFailed; import com.anwen.mongo.model.command.CommandStarted; import com.anwen.mongo.model.command.CommandSucceeded; @@ -11,21 +11,21 @@ import com.anwen.mongo.model.command.CommandSucceeded; * @description MongoPlus拦截器 * @date 2023-11-22 14:55 **/ -public class MongoPlusInterceptor implements Interceptor { +public class MongoPlusListener implements Listener { @Override public void commandStarted(CommandStarted commandStarted) { - InterceptorCache.interceptors.forEach(interceptor -> interceptor.commandStarted(commandStarted)); + ListenerCache.listeners.forEach(interceptor -> interceptor.commandStarted(commandStarted)); } @Override public void commandSucceeded(CommandSucceeded commandSucceeded) { - InterceptorCache.interceptors.forEach(interceptor -> interceptor.commandSucceeded(commandSucceeded)); + ListenerCache.listeners.forEach(interceptor -> interceptor.commandSucceeded(commandSucceeded)); } @Override public void commandFailed(CommandFailed commandFailed) { - InterceptorCache.interceptors.forEach(interceptor -> interceptor.commandFailed(commandFailed)); + ListenerCache.listeners.forEach(interceptor -> interceptor.commandFailed(commandFailed)); } @Override diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/business/BlockAttackInnerInterceptor.java b/mongo-plus-core/src/main/java/com/anwen/mongo/listener/business/BlockAttackInnerListener.java similarity index 85% rename from mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/business/BlockAttackInnerInterceptor.java rename to mongo-plus-core/src/main/java/com/anwen/mongo/listener/business/BlockAttackInnerListener.java index 83ca3c179b6c9e5638c2e26678c38b8aa99fec6a..bf15fd56580d7f954aa28d95d4030be2d4d86b17 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/business/BlockAttackInnerInterceptor.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/listener/business/BlockAttackInnerListener.java @@ -1,7 +1,7 @@ -package com.anwen.mongo.interceptor.business; +package com.anwen.mongo.listener.business; import com.anwen.mongo.cache.global.OrderCache; -import com.anwen.mongo.interceptor.Interceptor; +import com.anwen.mongo.listener.Listener; import com.anwen.mongo.model.command.CommandFailed; import com.anwen.mongo.model.command.CommandStarted; import com.anwen.mongo.model.command.CommandSucceeded; @@ -14,9 +14,9 @@ import org.slf4j.LoggerFactory; * * @author JiaChaoYang **/ -public class BlockAttackInnerInterceptor implements Interceptor { +public class BlockAttackInnerListener implements Listener { - Logger logger = LoggerFactory.getLogger(BlockAttackInnerInterceptor.class); + Logger logger = LoggerFactory.getLogger(BlockAttackInnerListener.class); @Override public void commandStarted(CommandStarted commandStarted) { diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/business/LogInterceptor.java b/mongo-plus-core/src/main/java/com/anwen/mongo/listener/business/LogListener.java similarity index 94% rename from mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/business/LogInterceptor.java rename to mongo-plus-core/src/main/java/com/anwen/mongo/listener/business/LogListener.java index 1339f05e2534477f2ed6d54130459c1298d369c0..986657e42fa1999b7bc43b028e78dac3fe49e3be 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/interceptor/business/LogInterceptor.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/listener/business/LogListener.java @@ -1,11 +1,11 @@ -package com.anwen.mongo.interceptor.business; +package com.anwen.mongo.listener.business; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; import com.anwen.mongo.cache.global.OrderCache; import com.anwen.mongo.cache.global.PropertyCache; -import com.anwen.mongo.interceptor.Interceptor; +import com.anwen.mongo.listener.Listener; import com.anwen.mongo.model.command.CommandFailed; import com.anwen.mongo.model.command.CommandStarted; import com.anwen.mongo.model.command.CommandSucceeded; @@ -17,7 +17,7 @@ import java.util.Objects; * @author JiaChaoYang * @date 2023/11/22 10:54 */ -public class LogInterceptor implements Interceptor { +public class LogListener implements Listener { private String formattingStatement(String statement){ return PropertyCache.format ? JSON.toJSONString(JSONObject.parse(statement), SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue, diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/manager/MongoPlusClient.java b/mongo-plus-core/src/main/java/com/anwen/mongo/manager/MongoPlusClient.java index 116972c4b8abf9fa97caf6a9c784119e2c737124..ce33ffaf088ae3c97a3acbf92d52e4c1d73d4671 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/manager/MongoPlusClient.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/manager/MongoPlusClient.java @@ -1,9 +1,14 @@ package com.anwen.mongo.manager; +import com.anwen.mongo.annotation.collection.CollectionName; import com.anwen.mongo.conn.CollectionManager; +import com.anwen.mongo.convert.CollectionNameConvert; import com.anwen.mongo.model.BaseProperty; +import com.anwen.mongo.toolkit.StringUtils; import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; +import org.bson.Document; import java.util.List; import java.util.Map; @@ -28,10 +33,59 @@ public class MongoPlusClient { */ private Map collectionManager; + private CollectionNameConvert collectionNameConvert; + + public CollectionNameConvert getCollectionNameConvert() { + return collectionNameConvert; + } + + public void setCollectionNameConvert(CollectionNameConvert collectionNameConvert) { + this.collectionNameConvert = collectionNameConvert; + } + public Map getCollectionManager() { return collectionManager; } + public MongoCollection getCollection(Class clazz){ + return getCollectionManager(clazz).getCollection(clazz); + } + + public MongoCollection getCollection(Class clazz,String collectionName){ + return getCollectionManager(clazz).getCollection(collectionName); + } + + public MongoCollection getCollection(String database,String collectionName){ + return getCollectionManager(database).getCollection(collectionName); + } + + public MongoCollection getCollection(String database,Class clazz){ + return getCollectionManager(database).getCollection(clazz); + } + + public CollectionManager getCollectionManager(Class clazz){ + String database = ""; + CollectionName collectionName = clazz.getAnnotation(CollectionName.class); + if (collectionName != null){ + database = collectionName.database(); + } + return getCollectionManager(database); + } + + public CollectionManager getCollectionManager(String database){ + Map managerMap = getCollectionManager(); + if (StringUtils.isBlank(database)){ + database = managerMap.keySet().stream().findFirst().get(); + } + CollectionManager collectionManager = managerMap.get(database); + if (null == collectionManager){ + collectionManager = new CollectionManager(getMongoClient(), collectionNameConvert, database); + getMongoDatabase().add(getMongoClient().getDatabase(database)); + getCollectionManager().put(database,collectionManager); + } + return collectionManager; + } + public void setCollectionManager(Map collectionManager) { this.collectionManager = collectionManager; } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/mapper/BaseMapper.java b/mongo-plus-core/src/main/java/com/anwen/mongo/mapper/BaseMapper.java index 582308b704641d24e2bd472170f1afbadbb2e374..bdfc5f2909c10ab6c439a62af260b29071307f5d 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/mapper/BaseMapper.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/mapper/BaseMapper.java @@ -1,11 +1,109 @@ package com.anwen.mongo.mapper; -import com.anwen.mongo.service.impl.ServiceImpl; +import com.anwen.mongo.conditions.aggregate.AggregateChainWrapper; +import com.anwen.mongo.conditions.interfaces.condition.CompareCondition; +import com.anwen.mongo.conditions.query.QueryChainWrapper; +import com.anwen.mongo.conditions.update.UpdateChainWrapper; +import com.anwen.mongo.execute.Execute; +import com.anwen.mongo.execute.ExecutorFactory; +import com.anwen.mongo.manager.MongoPlusClient; +import com.anwen.mongo.model.PageResult; +import com.mongodb.client.model.*; +import org.bson.Document; +import org.bson.conversions.Bson; + +import java.io.Serializable; +import java.util.Collection; +import java.util.List; + /** - * mapper层,待完善,占位 - * + * mapper层 + * TODO 名称待定,方法留CRUD,不同数据库实现该接口 * @author JiaChaoYang **/ -public class BaseMapper extends ServiceImpl { +public interface BaseMapper{ + + MongoPlusClient getMongoPlusClient(); + + default Execute getExecute(){ + return new ExecutorFactory().getExecute(); + } + + Document processIdField(T entity,Boolean skip); + + boolean save(T entity); + + Boolean saveBatch(Collection entityList); + + Long update(Bson queryBasic,Bson updateBasic,Class clazz); + + Integer bulkWrite(List> writeModelList,Class clazz); + + Boolean update(T entity,QueryChainWrapper queryChainWrapper); + + List list(Class clazz); + + List list(QueryChainWrapper queryChainWrapper, Class clazz); + + List aggregateList(AggregateChainWrapper queryChainWrapper, Class clazz); + + T one(QueryChainWrapper queryChainWrapper,Class clazz); + + @Deprecated + T limitOne(QueryChainWrapper queryChainWrapper,Class clazz); + + PageResult page(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize, Class clazz); + + List pageList(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize, Class clazz); + + PageResult page(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize, Integer recentPageNum, Class clazz); + + T getById(Serializable id,Class clazz); + + boolean isExist(Serializable id,Class clazz); + + boolean isExist(QueryChainWrapper queryChainWrapper,Class clazz); + + List getByIds(Collection ids,Class clazz); + + Boolean update(UpdateChainWrapper updateChainWrapper, Class clazz); + + Boolean remove(UpdateChainWrapper updateChainWrapper, Class clazz); + + Long remove(Bson filter,Class clazz); + + long count(QueryChainWrapper queryChainWrapper,Class clazz); + + long recentPageCount(List compareConditionList,Class clazz, Integer pageNum, Integer pageSize, Integer recentPageNum); + + long count(Class clazz); + + List queryCommand(String command,Class clazz); + + List getByColumn(String column,Object value,Class clazz); + + String createIndex(Bson bson,Class clazz); + + String createIndex(Bson bson, IndexOptions indexOptions, Class clazz); + + List createIndexes(List indexes,Class clazz); + + + List createIndexes(List indexes, CreateIndexOptions createIndexOptions,Class clazz); + + List listIndexes(Class clazz); + + void dropIndex(String indexName,Class clazz); + + void dropIndex(String indexName,DropIndexOptions dropIndexOptions,Class clazz); + + void dropIndex(Bson keys,Class clazz); + + void dropIndex(Bson keys,DropIndexOptions dropIndexOptions,Class clazz); + + void dropIndexes(Class clazz); + + void dropIndexes(DropIndexOptions dropIndexOptions,Class clazz); + } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/mapper/DefaultBaseMapperImpl.java b/mongo-plus-core/src/main/java/com/anwen/mongo/mapper/DefaultBaseMapperImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..abd5d187a9cff06c9411c874d16073f4992a38b8 --- /dev/null +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/mapper/DefaultBaseMapperImpl.java @@ -0,0 +1,549 @@ +package com.anwen.mongo.mapper; + +import com.anwen.mongo.annotation.ID; +import com.anwen.mongo.cache.global.HandlerCache; +import com.anwen.mongo.conditions.BuildCondition; +import com.anwen.mongo.conditions.aggregate.AggregateChainWrapper; +import com.anwen.mongo.conditions.interfaces.condition.CompareCondition; +import com.anwen.mongo.conditions.query.QueryChainWrapper; +import com.anwen.mongo.conditions.update.UpdateChainWrapper; +import com.anwen.mongo.constant.SqlOperationConstant; +import com.anwen.mongo.context.MongoTransactionContext; +import com.anwen.mongo.convert.CollectionNameConvert; +import com.anwen.mongo.convert.DocumentMapperConvert; +import com.anwen.mongo.enums.AggregateOptionsEnum; +import com.anwen.mongo.enums.IdTypeEnum; +import com.anwen.mongo.enums.SpecialConditionEnum; +import com.anwen.mongo.execute.Execute; +import com.anwen.mongo.execute.ExecutorFactory; +import com.anwen.mongo.manager.MongoPlusClient; +import com.anwen.mongo.model.*; +import com.anwen.mongo.strategy.convert.ConversionService; +import com.anwen.mongo.toolkit.*; +import com.mongodb.BasicDBObject; +import com.mongodb.bulk.BulkWriteResult; +import com.mongodb.client.AggregateIterable; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.model.*; +import com.mongodb.client.result.InsertManyResult; +import org.bson.Document; +import org.bson.conversions.Bson; +import org.bson.types.ObjectId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Serializable; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import static com.anwen.mongo.toolkit.BeanMapUtilByReflect.getIdField; + +/** + * baseMapper默认实现 + * + * @author JiaChaoYang + * @project mongo-plus + * @date 2024-02-05 11:47 + **/ +public class DefaultBaseMapperImpl implements BaseMapper { + private final Logger logger = LoggerFactory.getLogger(DefaultBaseMapperImpl.class); + + private final CollectionNameConvert collectionNameConvert; + + private final MongoPlusClient mongoPlusClient; + + private final LambdaOperate lambdaOperate = new LambdaOperate(); + + private final ExecutorFactory factory = new ExecutorFactory(); + + public DefaultBaseMapperImpl(MongoPlusClient mongoPlusClient) { + this.collectionNameConvert = mongoPlusClient.getCollectionNameConvert(); + this.mongoPlusClient = mongoPlusClient; + } + + @Override + public MongoPlusClient getMongoPlusClient() { + return mongoPlusClient; + } + + @Override + public boolean save(T entity){ + try { + Document document = processIdField(entity,false); + InsertManyResult insertManyResult = factory.getExecute().executeSave(Collections.singletonList(document), mongoPlusClient.getCollection(ClassTypeUtil.getClass(entity))); + setBackIdValue(document, entity); + return insertManyResult.wasAcknowledged(); + } catch (Exception e) { + logger.error("save fail , error info : {}", e.getMessage(), e); + return false; + } + } + + @Override + public Boolean saveBatch(Collection entityList) { + try { + List documentList = processIdFieldList(entityList); + MongoCollection collection = mongoPlusClient.getCollection(entityList.iterator().next().getClass()); + InsertManyResult insertManyResult = factory.getExecute().executeSave(documentList, collection); + return insertManyResult.getInsertedIds().size() == entityList.size(); + } catch (Exception e) { + logger.error("saveBatch fail , error info : {}", e.getMessage(), e); + return false; + } + } + + @Override + public Long update(Bson queryBasic, Bson updateBasic, Class clazz) { + return factory.getExecute().executeUpdate( + queryBasic, + updateBasic, + mongoPlusClient.getCollection(clazz) + ).getModifiedCount(); + } + + @Override + public Integer bulkWrite(List> writeModelList, Class clazz) { + BulkWriteResult bulkWriteResult = factory.getExecute().executeBulkWrite(writeModelList,mongoPlusClient.getCollection(clazz)); + return bulkWriteResult.getModifiedCount() + bulkWriteResult.getInsertedCount(); + } + + @Override + public Boolean update(T entity,QueryChainWrapper queryChainWrapper){ + MutablePair updatePair = getUpdateCondition(queryChainWrapper.getCompareList(), entity); + return factory.getExecute().executeUpdate(updatePair.getLeft(),updatePair.getRight(),mongoPlusClient.getCollection(ClassTypeUtil.getClass(entity))).getModifiedCount() > 0; + } + + private Boolean buildRemove(Serializable id, MongoCollection collection) { + Bson filterId = Filters.eq(SqlOperationConstant._ID, ObjectId.isValid(String.valueOf(id)) ? new ObjectId(String.valueOf(id)) : id); + return factory.getExecute().executeRemove(filterId,collection).getDeletedCount() >= 1; + } + + public Boolean executeRemoveByColumn(String column,Object value,MongoCollection collection){ + Bson filter = Filters.eq(column, ObjectId.isValid(String.valueOf(value)) ? new ObjectId(String.valueOf(value)) : value); + return factory.getExecute().executeRemove(filter,collection).getDeletedCount() >= 1; + } + + private Boolean executeRemoveBatchByIds(Collection idList,MongoCollection collection){ + List convertedIds = idList.stream() + .map(id -> ObjectId.isValid(String.valueOf(id)) ? new ObjectId(String.valueOf(id)) : id) + .collect(Collectors.toList()); + Bson objectIdBson = Filters.in(SqlOperationConstant._ID, convertedIds); + return factory.getExecute().executeRemove(objectIdBson,collection).getDeletedCount() >= 1; + } + + @Override + public List list(Class clazz) { + return DocumentMapperConvert.mapDocumentList(factory.getExecute().executeQuery(null,null,null,mongoPlusClient.getCollection(clazz),Document.class),clazz); + } + + @Override + public List list(QueryChainWrapper queryChainWrapper, Class clazz) { + BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(queryChainWrapper.getCompareList(),queryChainWrapper.getOrderList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList()); + return lambdaOperate.getLambdaQueryResult(factory.getExecute().executeQuery(baseLambdaQuery.getCondition(),baseLambdaQuery.getProjection(),baseLambdaQuery.getSort(),mongoPlusClient.getCollection(clazz),Document.class),clazz); + } + + @Override + public List aggregateList(AggregateChainWrapper queryChainWrapper, Class clazz){ + List aggregateList = queryChainWrapper.getBaseAggregateList(); + List basicDBObjectList = queryChainWrapper.getBasicDBObjectList(); + BasicDBObject optionsBasicDBObject = queryChainWrapper.getOptionsBasicDBObject(); + List aggregateConditionList = new ArrayList() {{ + aggregateList.forEach(aggregate -> add(new AggregateBasicDBObject("$" + aggregate.getType(), aggregate.getPipelineStrategy().buildAggregate(),aggregate.getOrder()))); + addAll(basicDBObjectList); + }}; + aggregateConditionList.sort(Comparator.comparingInt(AggregateBasicDBObject::getOrder)); + AggregateIterable aggregateIterable = factory.getExecute().executeAggregate(aggregateConditionList, mongoPlusClient.getCollection(clazz),Document.class); + aggregateOptions(aggregateIterable,optionsBasicDBObject); + return DocumentMapperConvert.mapDocumentList(aggregateIterable.iterator(),clazz); + } + + @Override + public T one(QueryChainWrapper queryChainWrapper,Class clazz) { + BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(queryChainWrapper.getCompareList(),null,queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList()); + return lambdaOperate.getLambdaQueryResultOne(factory.getExecute().executeQuery(baseLambdaQuery.getCondition(),baseLambdaQuery.getProjection(),baseLambdaQuery.getSort(),mongoPlusClient.getCollection(clazz),Document.class).limit(1),clazz); + } + + @Override + public T limitOne(QueryChainWrapper queryChainWrapper,Class clazz) { + BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(queryChainWrapper.getCompareList(),queryChainWrapper.getOrderList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList()); + return lambdaOperate.getLambdaQueryResultOne(factory.getExecute().executeQuery(baseLambdaQuery.getCondition(),baseLambdaQuery.getProjection(),baseLambdaQuery.getSort(),mongoPlusClient.getCollection(clazz),Document.class).limit(1),clazz); + } + + @Override + public PageResult page(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize,Class clazz) { + BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(queryChainWrapper.getCompareList(),queryChainWrapper.getOrderList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList()); + MongoCollection collection = mongoPlusClient.getCollection(clazz); + long count; + if (CollUtil.isEmpty(queryChainWrapper.getCompareList())){ + count = factory.getExecute().estimatedDocumentCount(collection); + }else { + count = count(queryChainWrapper,clazz); + } + FindIterable iterable = factory.getExecute().executeQuery(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collection,Document.class); + return lambdaOperate.getLambdaQueryResultPage(iterable,count,new PageParam(pageNum,pageSize),clazz); + } + + @Override + public List pageList(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize, Class clazz) { + BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(queryChainWrapper.getCompareList(),queryChainWrapper.getOrderList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList()); + FindIterable iterable = factory.getExecute().executeQuery(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), mongoPlusClient.getCollection(clazz),Document.class); + return DocumentMapperConvert.mapDocumentList(iterable.skip((pageNum - 1) * pageSize).limit(pageSize), clazz); + } + + @Override + public PageResult page(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize, Integer recentPageNum, Class clazz) { + BaseLambdaQueryResult baseLambdaQuery = lambdaOperate.baseLambdaQuery(queryChainWrapper.getCompareList(),queryChainWrapper.getOrderList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList()); + MongoCollection collection = mongoPlusClient.getCollection(clazz); + long count; + if (CollUtil.isEmpty(queryChainWrapper.getCompareList())){ + count = factory.getExecute().estimatedDocumentCount(collection); + }else { + count = recentPageCount(queryChainWrapper.getCompareList(),clazz, pageNum, pageSize, recentPageNum); + } + FindIterable iterable = factory.getExecute().executeQuery(baseLambdaQuery.getCondition(), baseLambdaQuery.getProjection(), baseLambdaQuery.getSort(), collection,Document.class); + return lambdaOperate.getLambdaQueryResultPage(iterable, count,new PageParam(pageNum,pageSize),clazz); + } + + @Override + public T getById(Serializable id,Class clazz) { + BasicDBObject queryBasic = new BasicDBObject(SqlOperationConstant._ID, new BasicDBObject(SpecialConditionEnum.EQ.getCondition(), ObjectId.isValid(String.valueOf(id)) ? new ObjectId(String.valueOf(id)) : id)); + return DocumentMapperConvert.mapDocument(factory.getExecute().executeQuery(queryBasic,null,null,mongoPlusClient.getCollection(clazz),Document.class).first(),clazz); + } + + @Override + public boolean isExist(Serializable id,Class clazz){ + BasicDBObject queryBasic = new BasicDBObject(SqlOperationConstant._ID, new BasicDBObject(SpecialConditionEnum.EQ.getCondition(), ObjectId.isValid(String.valueOf(id)) ? new ObjectId(String.valueOf(id)) : id)); + return factory.getExecute().executeCount(queryBasic,null, mongoPlusClient.getCollection(clazz)) >= 1; + } + + @Override + public boolean isExist(QueryChainWrapper queryChainWrapper,Class clazz){ + BasicDBObject basicDBObject = BuildCondition.buildQueryCondition(queryChainWrapper.getCompareList()); + return factory.getExecute().executeCount(basicDBObject,null,mongoPlusClient.getCollection(clazz)) >= 1; + } + + @Override + public List getByIds(Collection ids,Class clazz) { + BasicDBObject basicDBObject = checkIdType(ids); + FindIterable iterable = factory.getExecute().executeQuery(basicDBObject,null,null, mongoPlusClient.getCollection(clazz),Document.class); + return DocumentMapperConvert.mapDocumentList(iterable, clazz); + } + + @Override + public Boolean update(UpdateChainWrapper updateChainWrapper,Class clazz) { + List compareConditionList = new ArrayList<>(); + compareConditionList.addAll(updateChainWrapper.getCompareList()); + compareConditionList.addAll(updateChainWrapper.getUpdateCompareList()); + BasicDBObject queryBasic = BuildCondition.buildQueryCondition(compareConditionList); + List pushConditionList = compareConditionList.stream().filter(compareCondition -> Objects.equals(compareCondition.getCondition(), SpecialConditionEnum.PUSH.getSubCondition())).collect(Collectors.toList()); + List setConditionList = compareConditionList.stream().filter(compareCondition -> Objects.equals(compareCondition.getCondition(), SpecialConditionEnum.SET.getSubCondition())).collect(Collectors.toList()); + BasicDBObject basicDBObject = new BasicDBObject() {{ + if (CollUtil.isNotEmpty(setConditionList)){ + append(SpecialConditionEnum.SET.getCondition(), BuildCondition.buildUpdateValue(setConditionList)); + } + if (CollUtil.isNotEmpty(pushConditionList)){ + append(SpecialConditionEnum.PUSH.getCondition(), BuildCondition.buildPushUpdateValue(pushConditionList)); + } + }}; + return factory.getExecute().executeUpdate(queryBasic,DocumentUtil.handleBasicDBObject(basicDBObject),mongoPlusClient.getCollection(clazz)).getModifiedCount() >= 1; + } + + @Override + public Boolean remove(UpdateChainWrapper updateChainWrapper, Class clazz) { + return remove(BuildCondition.buildQueryCondition(updateChainWrapper.getCompareList()),clazz) >= 1; + } + + @Override + public Long remove(Bson filter, Class clazz) { + return factory.getExecute().executeRemove(filter,mongoPlusClient.getCollection(clazz)).getDeletedCount(); + } + + @Override + public long count(QueryChainWrapper queryChainWrapper,Class clazz){ + Execute execute = factory.getExecute(); + MongoCollection collection = mongoPlusClient.getCollection(clazz); + return Optional.ofNullable(queryChainWrapper.getCompareList()) + .map(compare -> execute.executeCount(BuildCondition.buildQueryCondition(compare),null,collection)) + .orElseGet(() -> execute.estimatedDocumentCount(collection)); + } + + /** + * 分页查询 查询总条数 + * @param compareConditionList 条件集合 + * @param clazz result class + * @param pageNum 当前页 + * @param pageSize 每页显示行数 + * @param recentPageNum 查询最近n页的数据 {参数=null 表示仅查询当前页数据} {参数取值[5-50] 表示查询最近[5-50]页的数据 建议recentPageNum等于10 参考 百度分页检索} + * @return long + */ + @Override + public long recentPageCount(List compareConditionList,Class clazz, Integer pageNum, Integer pageSize, Integer recentPageNum){ + if (recentPageNum == null || !(recentPageNum <= 50 && recentPageNum >= 5)) { + // 返回-1 表示不查询总条数 + return -1L; + } + //分页查询 不查询实际总条数 需要单独查询 是否有数据 + //如果recentPageNum = 10 第1-6页 总页数=10 从第7页开始 需要往后 + 4 页 + int limitParam = (pageNum < (recentPageNum / 2 + 1 + recentPageNum % 2) ? recentPageNum : (pageNum + (recentPageNum / 2 + recentPageNum % 2 - 1))) * pageSize; + CountOptions countOptions = new CountOptions(); + countOptions.skip(limitParam).limit(1); + long isExists = factory.getExecute().executeCount(BuildCondition.buildQueryCondition(compareConditionList),countOptions, mongoPlusClient.getCollection(clazz)); + //如果查询结果为空 则查询总条数,如果不为空则 limitParam为总条数 + if (isExists == 0) { + // 查询真实总条数 + CountOptions countOptionsReal = new CountOptions(); + countOptionsReal.limit(limitParam); + return factory.getExecute().executeCount(BuildCondition.buildQueryCondition(compareConditionList),countOptions, mongoPlusClient.getCollection(clazz)); + } + return limitParam; + } + + @Override + public long count(Class clazz){ + return factory.getExecute().estimatedDocumentCount(mongoPlusClient.getCollection(clazz)); + } + + @Override + public List queryCommand(String command,Class clazz){ + FindIterable iterable = factory.getExecute().executeQuery(BasicDBObject.parse(command),null,null, mongoPlusClient.getCollection(clazz),Document.class); + return lambdaOperate.getLambdaQueryResult(iterable,clazz); + } + + @Override + public List getByColumn(String column,Object value,Class clazz){ + Bson filter = Filters.eq(column, ObjectId.isValid(String.valueOf(value)) ? new ObjectId(String.valueOf(value)) : value); + return DocumentMapperConvert.mapDocumentList(factory.getExecute().executeQuery(filter,null,null,mongoPlusClient.getCollection(clazz),Document.class),clazz); + } + + @Override + public String createIndex(Bson bson,Class clazz){ + return factory.getExecute().doCreateIndex(bson,mongoPlusClient.getCollection(clazz)); + } + + @Override + public String createIndex(Bson bson, IndexOptions indexOptions, Class clazz){ + return factory.getExecute().doCreateIndex(bson,indexOptions,mongoPlusClient.getCollection(clazz)); + } + + @Override + public List createIndexes(List indexes,Class clazz){ + return factory.getExecute().doCreateIndexes(indexes,mongoPlusClient.getCollection(clazz)); + } + + @Override + public List createIndexes(List indexes, CreateIndexOptions createIndexOptions,Class clazz){ + return factory.getExecute().doCreateIndexes(indexes,createIndexOptions,mongoPlusClient.getCollection(clazz)); + } + + @Override + public List listIndexes(Class clazz){ + return factory.getExecute().doListIndexes(mongoPlusClient.getCollection(clazz)); + } + + @Override + public void dropIndex(String indexName,Class clazz){ + factory.getExecute().doDropIndex(indexName,mongoPlusClient.getCollection(clazz)); + } + + @Override + public void dropIndex(String indexName,DropIndexOptions dropIndexOptions,Class clazz){ + factory.getExecute().doDropIndex(indexName,dropIndexOptions,mongoPlusClient.getCollection(clazz)); + } + + @Override + public void dropIndex(Bson keys,Class clazz){ + factory.getExecute().doDropIndex(keys,mongoPlusClient.getCollection(clazz)); + } + + @Override + public void dropIndex(Bson keys,DropIndexOptions dropIndexOptions,Class clazz){ + factory.getExecute().doDropIndex(keys,dropIndexOptions,mongoPlusClient.getCollection(clazz)); + } + + @Override + public void dropIndexes(Class clazz){ + factory.getExecute().doDropIndexes(mongoPlusClient.getCollection(clazz)); + } + + @Override + public void dropIndexes(DropIndexOptions dropIndexOptions,Class clazz){ + factory.getExecute().doDropIndexes(dropIndexOptions,mongoPlusClient.getCollection(clazz)); + } + + protected MutablePair getUpdate(T entity){ + Document document = DocumentUtil.checkUpdateField(entity,false); + BasicDBObject filter = ExecuteUtil.getFilter(document); + BasicDBObject update = new BasicDBObject(SpecialConditionEnum.SET.getCondition(), document); + return new MutablePair<>(filter,update); + } + + protected BasicDBObject checkIdType(Collection ids) { + List convertedIds = ids.stream() + .map(id -> ObjectId.isValid(String.valueOf(id)) ? new ObjectId(String.valueOf(id)) : id) + .collect(Collectors.toList()); + return new BasicDBObject(SqlOperationConstant._ID, new BasicDBObject(SpecialConditionEnum.IN.getCondition(), convertedIds)); + } + + protected MutablePair getUpdateCondition(List compareConditionList, T entity){ + BasicDBObject queryBasic = BuildCondition.buildQueryCondition(compareConditionList); + Document document = DocumentUtil.checkUpdateField(entity,false); + document.remove(SqlOperationConstant._ID); + BasicDBObject updateField = new BasicDBObject(SpecialConditionEnum.SET.getCondition(), document); + return new MutablePair<>(queryBasic,updateField); + } + + @Override + public Document processIdField(T entity,Boolean skip){ + Document tableFieldMap = DocumentUtil.checkTableField(entity); + fillId(entity, tableFieldMap); + if (HandlerCache.documentHandler != null && !skip){ + //经过一下Document处理器 + tableFieldMap = HandlerCache.documentHandler.insertInvoke(Collections.singletonList(tableFieldMap)).get(0); + } + return tableFieldMap; + } + + protected Integer getAutoId(Class clazz) { + String collectionName = collectionNameConvert.convert(clazz); + // 每个Collection单独加锁 + synchronized (collectionName.intern()) { + MongoCollection collection = mongoPlusClient.getCollection(clazz,"counters"); + Document query = new Document(SqlOperationConstant._ID, collectionName); + Document update = new Document("$inc", new Document(SqlOperationConstant.AUTO_NUM, 1)); + Document document = Optional.ofNullable(MongoTransactionContext.getClientSessionContext()) + .map(session -> collection.findOneAndUpdate(session, query, update, new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER))) + .orElseGet(() -> collection.findOneAndUpdate(query, update, new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER))); + int finalNum = 1; + if (document == null) { + Map map = new HashMap<>(); + map.put(SqlOperationConstant._ID, collectionNameConvert.convert(clazz)); + map.put(SqlOperationConstant.AUTO_NUM, finalNum); + collection.insertOne(new Document(map)); + } else { + finalNum = Integer.parseInt(String.valueOf(document.get(SqlOperationConstant.AUTO_NUM))); + } + return finalNum; + } + } + + protected void fillId(T entity, Document document) { + // 用户自行设置了id字段 + if (document.containsKey(SqlOperationConstant._ID)) { + // 检查一边id的入库类型 + Object idObj = document.get(SqlOperationConstant._ID); + if (ObjectId.isValid(String.valueOf(idObj)) && !idObj.getClass().equals(ObjectId.class)) { + document.put(SqlOperationConstant._ID, new ObjectId(String.valueOf(idObj))); + } + return; + } + java.lang.reflect.Field idField = getIdField(ClassTypeUtil.getClass(entity)); + // 没有指定id字段 + if (idField == null) { + return; + } + ID annotation = idField.getAnnotation(ID.class); + Object _idValue; + if (annotation.type() == IdTypeEnum.AUTO) { + _idValue = getAutoId(ClassTypeUtil.getClass(entity)); + } else { + if (annotation.type() == IdTypeEnum.OBJECT_ID){ + return; + } + _idValue = Generate.generateId(annotation.type()); + } + try { + Object value = ConversionService.convertValue(idField, ClassTypeUtil.getClass(entity).getDeclaredConstructor().newInstance(), _idValue); + document.put(SqlOperationConstant._ID, value); + //为自行设置id,需要在这里判断一下重入,自行设置checkTableField方法会进行处理 + if (annotation.saveField()){ + document.put(idField.getName(),value); + } + } catch (IllegalAccessException | InstantiationException | InvocationTargetException | + NoSuchMethodException e) { + logger.error("Failed to convert to entity class's' _id 'field type when filling in'_id',error message: {}",e.getMessage(),e); + throw new RuntimeException(e); + } + } + + protected void setBackIdValue(Document document, T entity) { + Object idValue = document.get(SqlOperationConstant._ID); + if (idValue == null) { + return; + } + Field idField = getIdField(ClassTypeUtil.getClass(entity)); + if (idField == null) { + return; + } + if (ReflectionUtils.getFieldValue(entity, idField) != null) { + return; + } + try { + //使用策略转换器回写id + ConversionService.setValue(idField,entity,idValue); + } catch (Exception e) { + logger.error("set back id field value error, error message: {}", e.getMessage()); + } + } + + protected void ifPresentOrElse(T value, Consumer action, Runnable emptyAction) { + if (value != null) { + action.accept(value); + } else { + emptyAction.run(); + } + } + + protected List processIdFieldList(Collection entityList){ + List documentList = entityList.stream().map(document -> processIdField(document,true)).collect(Collectors.toList()); + return Optional.ofNullable(HandlerCache.documentHandler).map(documentHandler -> documentHandler.insertInvoke(documentList)).orElse(documentList); + } + + protected void aggregateOptions(AggregateIterable aggregateIterable,BasicDBObject optionsBasicDBObject){ + options(aggregateIterable, optionsBasicDBObject); + } + + public static void options(AggregateIterable aggregateIterable, BasicDBObject optionsBasicDBObject) { + Set keyedSet = optionsBasicDBObject.keySet(); + for (String key : keyedSet) { + AggregateOptionsEnum aggregateOptionsEnum = AggregateOptionsEnum.getByOptions(key); + switch (Objects.requireNonNull(aggregateOptionsEnum)){ + case ALLOW_DISK_USE: + aggregateIterable.allowDiskUse(optionsBasicDBObject.getBoolean(key)); + break; + case COLLATION: + aggregateIterable.collation((Collation) optionsBasicDBObject.get(key)); + break; + case BATCH_SIZE: + aggregateIterable.batchSize(optionsBasicDBObject.getInt(key)); + break; + case MAX_TIME_MS: + aggregateIterable.maxTime(optionsBasicDBObject.getLong(key), TimeUnit.MILLISECONDS); + break; + case MAX_AWAIT_TIME_MS: + aggregateIterable.maxAwaitTime(optionsBasicDBObject.getLong(key),TimeUnit.MILLISECONDS); + break; + case BYPASS_DOCUMENT_VALIDATION: + aggregateIterable.bypassDocumentValidation(optionsBasicDBObject.getBoolean(key)); + break; + case COMMENT: + aggregateIterable.comment(String.valueOf(optionsBasicDBObject.get(key))); + break; + case COMMENT_STR: + aggregateIterable.comment(optionsBasicDBObject.getString(key)); + break; + case HINT: + aggregateIterable.hint((Bson) optionsBasicDBObject.get(key)); + break; + case LET: + aggregateIterable.let((Bson) optionsBasicDBObject.get(key)); + break; + } + } + } + +} diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/mapper/MongoPlusMapMapper.java b/mongo-plus-core/src/main/java/com/anwen/mongo/mapper/MongoPlusMapMapper.java index 9f6b1731775c717b791d68bbfc39c1065b66dacb..f7d499d7fa7fe35661e6b5919eca04f0d4add4a2 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/mapper/MongoPlusMapMapper.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/mapper/MongoPlusMapMapper.java @@ -1,3 +1,4 @@ + package com.anwen.mongo.mapper; import com.anwen.mongo.conditions.aggregate.AggregateChainWrapper; @@ -9,6 +10,7 @@ import com.anwen.mongo.conditions.interfaces.condition.CompareCondition; import com.anwen.mongo.conditions.query.QueryChainWrapper; import com.anwen.mongo.conditions.update.UpdateChainWrapper; import com.anwen.mongo.execute.ExecutorFactory; +import com.anwen.mongo.manager.MongoPlusClient; import com.anwen.mongo.model.PageParam; import com.anwen.mongo.model.PageResult; import com.mongodb.client.MongoCollection; @@ -30,11 +32,15 @@ import static com.anwen.mongo.toolkit.StringPool.EMPTY; /** * @author JiaChaoYang **/ + public class MongoPlusMapMapper implements InjectQuery { private final ExecutorFactory factory; - public MongoPlusMapMapper(ExecutorFactory factory) { - this.factory = factory; + private final MongoPlusClient mongoPlusClient; + + public MongoPlusMapMapper(MongoPlusClient mongoPlusClient) { + this.mongoPlusClient = mongoPlusClient; + factory = new ExecutorFactory(mongoPlusClient); } /** @@ -43,7 +49,7 @@ public class MongoPlusMapMapper implements InjectQuery { * @date 2023/11/15 13:43 */ public MongoCollection getMongoCollection(String database,String collectionName){ - return factory.getCollectionManager(database).getCollection(collectionName); + return mongoPlusClient.getCollection(database,collectionName); } /** @@ -52,7 +58,7 @@ public class MongoPlusMapMapper implements InjectQuery { * @date 2023/11/15 13:43 */ public MongoCollection getMongoCollection(String collectionName){ - return factory.getCollectionManager(EMPTY).getCollection(collectionName); + return mongoPlusClient.getCollection(EMPTY,collectionName); } public LambdaQueryChainInjectWrapper lambdaQuery(){ @@ -340,6 +346,36 @@ public class MongoPlusMapMapper implements InjectQuery { return factory.getInjectExecute(database).queryCommand(collectionName,command); } + @Override + public Boolean exist(String collectionName, Serializable id) { + return exist(EMPTY,collectionName,id); + } + + @Override + public Boolean exist(String database, String collectionName, Serializable id) { + return factory.getInjectExecute(database).isExist(collectionName,id); + } + + @Override + public Boolean exist(String collectionName, QueryChainWrapper, ?> queryChainWrapper) { + return exist(EMPTY,collectionName,queryChainWrapper); + } + + @Override + public Boolean exist(String database, String collectionName, QueryChainWrapper, ?> queryChainWrapper) { + return factory.getInjectExecute(database).isExist(collectionName,queryChainWrapper); + } + + @Override + public Boolean update(String collectionName, Map entityMap, QueryChainWrapper, ?> queryChainWrapper) { + return update(EMPTY,collectionName,entityMap,queryChainWrapper); + } + + @Override + public Boolean update(String database, String collectionName, Map entityMap, QueryChainWrapper, ?> queryChainWrapper) { + return null; + } + @Override public String createIndex(String collectionName,Bson bson) { return createIndex(EMPTY,collectionName,bson); diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/model/MutablePair.java b/mongo-plus-core/src/main/java/com/anwen/mongo/model/MutablePair.java new file mode 100644 index 0000000000000000000000000000000000000000..32b764a5bea38ca11a8818b9eae1fa79d41ca1c2 --- /dev/null +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/model/MutablePair.java @@ -0,0 +1,105 @@ +package com.anwen.mongo.model; + +/** + * 可变的Pair + * + * @author JiaChaoYang + **/ +public class MutablePair extends Pair { + + /** + * 左侧对象 + * @author JiaChaoYang + * @date 2024/3/16 22:49 + */ + public L left; + + /** + * 右侧对象 + * @author JiaChaoYang + * @date 2024/3/16 22:49 + */ + public R right; + + /** + * 从两个推断泛型类型的对象中获得一对不可变的。 + * 这个工厂允许使用推理来创建对,以获得泛型类型。 + * @author JiaChaoYang + * @date 2024/3/16 22:49 + */ + public static MutablePair of(final L left, final R right) { + return new MutablePair<>(left, right); + } + + /** + * 创建两个null的新对实例 + * @author JiaChaoYang + * @date 2024/3/16 22:49 + */ + public MutablePair() { + super(); + } + + /** + * 创建一个新的配对实例。 + * @author JiaChaoYang + * @date 2024/3/16 22:50 + */ + public MutablePair(final L left, final R right) { + super(); + this.left = left; + this.right = right; + } + + //----------------------------------------------------------------------- + /** + * {@inheritDoc} + * @author JiaChaoYang + * @date 2024/3/16 22:50 + */ + @Override + public L getLeft() { + return left; + } + + /** + * 设置该对的左侧元素 + * @author JiaChaoYang + * @date 2024/3/16 22:50 + */ + public void setLeft(final L left) { + this.left = left; + } + + /** + * {@inheritDoc} + * @author JiaChaoYang + * @date 2024/3/16 22:50 + */ + @Override + public R getRight() { + return right; + } + + /** + * 设置对的右侧元素 + * @author JiaChaoYang + * @date 2024/3/16 22:51 + */ + public void setRight(final R right) { + this.right = right; + } + + /** + * 这设置了对中正确的元素 + * @author JiaChaoYang + * @date 2024/3/16 22:51 + */ + @Override + public R setValue(final R value) { + final R result = getRight(); + setRight(value); + return result; + } + +} diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/model/Pair.java b/mongo-plus-core/src/main/java/com/anwen/mongo/model/Pair.java new file mode 100644 index 0000000000000000000000000000000000000000..b59bdc85a880cd0daa869e0e06cbd0619a7d9a12 --- /dev/null +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/model/Pair.java @@ -0,0 +1,124 @@ +package com.anwen.mongo.model; + +import com.anwen.mongo.toolkit.builder.CompareToBuilder; + +import java.io.Serializable; +import java.util.Map; +import java.util.Objects; + +/** + * 由两个元素组成的一对。 + * 这个类是定义基本API的抽象实现。它将元素称为“左”和“右”。它还实现了Map。输入接口,其中键为“left”,值为“right”。 + * 子类实现可以是可变的,也可以是不可变的。然而,对可以存储的存储对象的类型没有限制。如果可变对象存储在对中,那么对本身实际上就是可变的。 + * @author JiaChaoYang + **/ +public abstract class Pair implements Map.Entry, Comparable>, Serializable { + + + private static final long serialVersionUID = 5257775966081801053L; + + /** + * 从两个推断泛型类型的对象中获得一对不可变的。 + * 这个工厂允许使用推理来创建对,以获得泛型类型 + * @author JiaChaoYang + * @date 2024/3/16 22:48 + */ + public static Pair of(final L left, final R right) { + return new MutablePair<>(left, right); + } + + /** + * 从该对中获取左侧元素 + * @author JiaChaoYang + * @date 2024/3/16 22:47 + */ + public abstract L getLeft(); + + /** + * 从这对中获取右侧元素 + * @author JiaChaoYang + * @date 2024/3/16 22:47 + */ + public abstract R getRight(); + + /** + * 从这对中获取KEY。 + * @author JiaChaoYang + * @date 2024/3/16 22:47 + */ + @Override + public final L getKey() { + return getLeft(); + } + + /** + * 从该对中获取值 + * @author JiaChaoYang + * @date 2024/3/16 22:47 + */ + @Override + public R getValue() { + return getRight(); + } + + /** + * 比较基于左元素和右元素的对。类型必须是可比较的。 + * @author JiaChaoYang + * @date 2024/3/16 22:47 + */ + @Override + public int compareTo(final Pair other) { + return new CompareToBuilder().append(getLeft(), other.getLeft()) + .append(getRight(), other.getRight()).toComparison(); + } + + /** + * 根据这两个元素将此对与另一对进行比较。 + * @author JiaChaoYang + * @date 2024/3/16 22:46 + */ + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof Map.Entry) { + final Map.Entry other = (Map.Entry) obj; + return Objects.equals(getKey(), other.getKey()) + && Objects.equals(getValue(), other.getValue()); + } + return false; + } + + /** + * 返回合适的哈希代码。哈希代码遵循Map中的定义 + * @author JiaChaoYang + * @date 2024/3/16 22:52 + */ + @Override + public int hashCode() { + // see Map.Entry API specification + return (getKey() == null ? 0 : getKey().hashCode()) ^ + (getValue() == null ? 0 : getValue().hashCode()); + } + + /** + * 使用格式($left,$right)返回此对的字符串表示形式 + * @author JiaChaoYang + * @date 2024/3/16 22:52 + */ + @Override + public String toString() { + return new StringBuilder().append('(').append(getLeft()).append(',').append(getRight()).append(')').toString(); + } + + /** + * 使用给定的格式格式化接收器。 + * 这使用java.util。Formattable以执行格式化。可以使用两个变量来嵌入左元素和右元素。将%1$s用于左侧元素(键),将%2$s用于右侧元素(值)。toString()使用的默认格式是(%1$s,%2$s)。 + * @author JiaChaoYang + * @date 2024/3/16 22:52 + */ + public String toString(final String format) { + return String.format(format, getLeft(), getRight()); + } +} diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/model/QueryParam.java b/mongo-plus-core/src/main/java/com/anwen/mongo/model/QueryParam.java new file mode 100644 index 0000000000000000000000000000000000000000..6b79faa468ba3170c862ef7ac4a0df179dc2df12 --- /dev/null +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/model/QueryParam.java @@ -0,0 +1,86 @@ +package com.anwen.mongo.model; + +import com.mongodb.BasicDBObject; +import org.bson.conversions.Bson; + +import java.util.Objects; + +/** + * 查询拦截器需要的值 + * + * @author JiaChaoYang + **/ +public class QueryParam { + public QueryParam(Bson query, BasicDBObject projection, BasicDBObject sort) { + this.query = query; + this.projection = projection; + this.sort = sort; + } + + /** + * 查询参数(第一个) + * @author JiaChaoYang + * @date 2024/3/17 0:15 + */ + private Bson query; + + /** + * project(第二个) + * @author JiaChaoYang + * @date 2024/3/17 0:15 + */ + private BasicDBObject projection; + + /** + * 排序(第三个) + * @author JiaChaoYang + * @date 2024/3/17 0:15 + */ + private BasicDBObject sort; + + public Bson getQuery() { + return query; + } + + public void setQuery(Bson query) { + this.query = query; + } + + public BasicDBObject getProjection() { + return projection; + } + + public void setProjection(BasicDBObject projection) { + this.projection = projection; + } + + public BasicDBObject getSort() { + return sort; + } + + public void setSort(BasicDBObject sort) { + this.sort = sort; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof QueryParam)) return false; + QueryParam that = (QueryParam) o; + return Objects.equals(getQuery(), that.getQuery()) && Objects.equals(getProjection(), that.getProjection()) && Objects.equals(getSort(), that.getSort()); + } + + @Override + public int hashCode() { + return Objects.hash(getQuery(), getProjection(), getSort()); + } + + @Override + public String toString() { + return "QueryParam{" + + "query=" + query + + ", projection=" + projection + + ", sort=" + sort + + '}'; + } +} diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/proxy/ExecutorProxy.java b/mongo-plus-core/src/main/java/com/anwen/mongo/proxy/ExecutorProxy.java new file mode 100644 index 0000000000000000000000000000000000000000..301fe4593a64b72982ddca4c8cfefe10082ce17b --- /dev/null +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/proxy/ExecutorProxy.java @@ -0,0 +1,69 @@ +package com.anwen.mongo.proxy; + +import com.anwen.mongo.cache.global.InterceptorCache; +import com.anwen.mongo.enums.ExecuteMethodEnum; +import com.anwen.mongo.execute.Execute; +import com.anwen.mongo.model.AggregateBasicDBObject; +import com.anwen.mongo.model.MutablePair; +import com.anwen.mongo.model.QueryParam; +import com.mongodb.BasicDBObject; +import com.mongodb.client.model.CountOptions; +import com.mongodb.client.model.WriteModel; +import org.bson.Document; +import org.bson.conversions.Bson; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.List; + +/** + * 执行器代理 + * + * @author JiaChaoYang + * @project mongo-plus + * @date 2024-02-05 09:15 + **/ +public class ExecutorProxy implements InvocationHandler { + + private final Execute target; + + public ExecutorProxy(Execute target) { + this.target = target; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + String name = method.getName(); + InterceptorCache.interceptors.forEach(interceptor -> { + if (name.equals(ExecuteMethodEnum.SAVE.getMethod())){ + args[0] = interceptor.executeSave((List) args[0]); + } + if (name.equals(ExecuteMethodEnum.REMOVE.getMethod())){ + args[0] = interceptor.executeRemove((Bson) args[0]); + } + if (name.equals(ExecuteMethodEnum.UPDATE.getMethod())){ + MutablePair bsonBsonMutablePair = interceptor.executeUpdate((Bson) args[0], (Bson) args[1]); + args[0] = bsonBsonMutablePair.getLeft(); + args[1] = bsonBsonMutablePair.getRight(); + } + if (name.equals(ExecuteMethodEnum.QUERY.getMethod())){ + QueryParam queryParam = interceptor.executeQuery((Bson) args[0], (BasicDBObject) args[1], (BasicDBObject) args[2]); + args[0] = queryParam.getQuery(); + args[1] = queryParam.getProjection(); + args[2] = queryParam.getSort(); + } + if (name.equals(ExecuteMethodEnum.AGGREGATE.getMethod())){ + args[0] = interceptor.executeAggregate((List) args[0]); + } + if (name.equals(ExecuteMethodEnum.COUNT.getMethod())){ + MutablePair basicDBObjectCountOptionsMutablePair = interceptor.executeCount((BasicDBObject) args[0], (CountOptions) args[1]); + args[0] = basicDBObjectCountOptionsMutablePair.getLeft(); + args[1] = basicDBObjectCountOptionsMutablePair.getRight(); + } + if (name.equals(ExecuteMethodEnum.BULK_WRITE.getMethod())){ + args[0] = interceptor.executeBulkWrite((List>) args[0]); + } + }); + return method.invoke(target, args); + } +} diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/service/IService.java b/mongo-plus-core/src/main/java/com/anwen/mongo/service/IService.java index 669233fbb18d13d1e87b017b4b68d29ca9c31003..9ef3877aacdf0d47738faef5b23a84247d611358 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/service/IService.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/service/IService.java @@ -56,7 +56,7 @@ public interface IService { Boolean saveOrUpdate(T entity); /** - * 根据传入wrapper条件判断添加还是删除,传递_id并不会修改 + * 根据传入wrapper条件判断添加修改,传递_id并不会修改 * @param entity 对象 * @param queryChainWrapper 条件 * @return java.lang.Boolean @@ -74,6 +74,15 @@ public interface IService { */ Boolean saveOrUpdateBatch(Collection entityList); + /** + * 根据传入wrapper条件判断批量添加修改,传递_id并不会修改 + * @param entityList 对象集合 + * @return java.lang.Boolean + * @author JiaChaoYang + * @since 2023/2/9 13:57 + */ + Boolean saveOrUpdateBatchWrapper(Collection entityList,QueryChainWrapper queryChainWrapper); + /** * 修改 * @param entity 修改的对象,需要包含id @@ -115,6 +124,13 @@ public interface IService { */ Boolean update(UpdateChainWrapper updateChainWrapper); + /** + * 根据条件修改 + * @author JiaChaoYang + * @date 2024/2/3 13:10 + */ + Boolean update(T entity,QueryChainWrapper queryChainWrapper); + /** * 根据id删除 * @param id 数据id @@ -171,6 +187,7 @@ public interface IService { * @author JiaChaoYang * @date 2023/7/20 23:20 */ + @Deprecated T limitOne(QueryChainWrapper queryChainWrapper); List list(QueryChainWrapper queryChainWrapper); @@ -190,6 +207,16 @@ public interface IService { */ PageResult page(PageParam pageParam); + /** + * 分页查询 + * @param pageParam 分页参数对象 + * @param recentPageNum 查询最近n页的数据 {参数=null 表示仅查询当前页数据} {参数取值[5-50] 表示查询最近[5-50]页的数据 建议recentPageNum等于10 参考 百度分页检索} + * @return com.anwen.mongo.sql.model.PageResult + * @author JiaChaoYang + * @date 2023/6/25/025 + */ + PageResult page(PageParam pageParam, Integer recentPageNum); + /** * 分页查询 * @param pageNum 当前页 @@ -200,10 +227,56 @@ public interface IService { */ PageResult page(Integer pageNum,Integer pageSize); + /** + * 分页查询 + * @param pageNum 当前页 + * @param pageSize 每页显示行数 + * @param recentPageNum 查询最近n页的数据 {参数=null 表示仅查询当前页数据} {参数取值[5-50] 表示查询最近[5-50]页的数据 建议recentPageNum等于10 参考 百度分页检索} + * @return com.anwen.mongo.sql.model.PageResult + * @author JiaChaoYang + * @date 2023/6/25/025 + */ + PageResult page(Integer pageNum,Integer pageSize, Integer recentPageNum); + PageResult page(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize); PageResult page(QueryChainWrapper queryChainWrapper, PageParam pageParam); + PageResult page(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize, Integer recentPageNum); + + PageResult page(QueryChainWrapper queryChainWrapper, PageParam pageParam, Integer recentPageNum); + + /** + * 返回List的page,无需进行count查询,速度会比较快 + * @author JiaChaoYang + * @date 2024/3/16 23:56 + */ + List pageList(PageParam pageParam); + + /** + * 返回List的page,无需进行count查询,速度会比较快 + * + * @author JiaChaoYang + * @date 2024/3/16 23:56 + */ + List pageList(Integer pageNum,Integer pageSize); + + /** + * 返回List的page,无需进行count查询,速度会比较快 + * + * @author JiaChaoYang + * @date 2024/3/16 23:56 + */ + List pageList(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize); + + /** + * 返回List的page,无需进行count查询,速度会比较快 + * + * @author JiaChaoYang + * @date 2024/3/16 23:56 + */ + List pageList(QueryChainWrapper queryChainWrapper, PageParam pageParam); + /** * 根据id查询单个 * @param id id @@ -244,6 +317,24 @@ public interface IService { */ List getByColumn(String field,Object fieldValue); + /** + * 是否存在 + * @param id id + * @return java.lang.Boolean + * @author JiaChaoYang + * @date 2024/2/3 13:42 + */ + Boolean exist(Serializable id); + + /** + * 是否存在 + * @param queryChainWrapper wrapper条件 + * @return java.lang.Boolean + * @author JiaChaoYang + * @date 2024/2/3 13:41 + */ + Boolean exist(QueryChainWrapper queryChainWrapper); + /** * 创建索引 * @param bson 描述索引键的对象,该对象不能为 null diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/service/impl/ServiceImpl.java b/mongo-plus-core/src/main/java/com/anwen/mongo/service/impl/ServiceImpl.java index 24f8930a369ef1f8ac1ad1ee8a0a31fc309dde98..cbf570e8a14d6daaaf6f48a736619322b26e041c 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/service/impl/ServiceImpl.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/service/impl/ServiceImpl.java @@ -1,25 +1,29 @@ package com.anwen.mongo.service.impl; +import com.anwen.mongo.conditions.BuildCondition; import com.anwen.mongo.conditions.aggregate.AggregateChainWrapper; import com.anwen.mongo.conditions.aggregate.LambdaAggregateChainWrapper; import com.anwen.mongo.conditions.interfaces.condition.CompareCondition; import com.anwen.mongo.conditions.query.LambdaQueryChainWrapper; import com.anwen.mongo.conditions.query.QueryChainWrapper; +import com.anwen.mongo.conditions.query.QueryWrapper; import com.anwen.mongo.conditions.update.LambdaUpdateChainWrapper; import com.anwen.mongo.conditions.update.UpdateChainWrapper; -import com.anwen.mongo.execute.ExecutorFactory; +import com.anwen.mongo.constant.SqlOperationConstant; +import com.anwen.mongo.enums.SpecialConditionEnum; +import com.anwen.mongo.mapper.BaseMapper; +import com.anwen.mongo.model.MutablePair; import com.anwen.mongo.model.PageParam; import com.anwen.mongo.model.PageResult; import com.anwen.mongo.service.IService; import com.anwen.mongo.support.SFunction; -import com.anwen.mongo.toolkit.ChainWrappers; +import com.anwen.mongo.toolkit.*; +import com.mongodb.BasicDBObject; import com.mongodb.client.MongoCollection; -import com.mongodb.client.model.CreateIndexOptions; -import com.mongodb.client.model.DropIndexOptions; -import com.mongodb.client.model.IndexModel; -import com.mongodb.client.model.IndexOptions; +import com.mongodb.client.model.*; import org.bson.Document; import org.bson.conversions.Bson; +import org.bson.types.ObjectId; import java.io.Serializable; import java.lang.reflect.ParameterizedType; @@ -28,6 +32,7 @@ import java.lang.reflect.TypeVariable; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; /** * @author JiaChaoYang @@ -36,14 +41,10 @@ import java.util.List; **/ public class ServiceImpl implements IService{ - private ExecutorFactory factory; + private BaseMapper baseMapper; - public void setFactory(ExecutorFactory factory){ - this.factory = factory; - } - - public ExecutorFactory getFactory(){ - return factory; + public void setBaseMapper(BaseMapper baseMapper){ + this.baseMapper = baseMapper; } private Class clazz; @@ -84,140 +85,239 @@ public class ServiceImpl implements IService{ @Override public MongoCollection getCollection() { - return factory.getCollectionManager(database).getCollection(clazz); + return baseMapper.getMongoPlusClient().getCollection(database,clazz); } @Override public MongoCollection getCollection(String database) { - return factory.getCollectionManager(database).getCollection(clazz); + return baseMapper.getMongoPlusClient().getCollection(database,clazz); } @Override public Boolean save(T entity) { - return factory.getExecute(database).save(entity); + return baseMapper.save(entity); } @Override public Boolean saveBatch(Collection entityList) { - return factory.getExecute(database).saveBatch(entityList); + return baseMapper.saveBatch(entityList); } @Override public Boolean saveOrUpdate(T entity) { - return factory.getExecute(database).saveOrUpdate(entity); + String idByEntity = ClassTypeUtil.getIdByEntity(entity, true); + if (StringUtils.isBlank(idByEntity)){ + return save(entity); + } + return updateById(entity); } @Override public Boolean saveOrUpdateWrapper(T entity, QueryChainWrapper queryChainWrapper) { - return factory.getExecute(database).saveOrUpdateWrapper(entity,queryChainWrapper.getCompareList()); + long count = count(queryChainWrapper); + if (count > 0){ + MutablePair updatePair = getUpdateCondition(queryChainWrapper.getCompareList(), entity); + return baseMapper.update(updatePair.getLeft(),updatePair.getRight(),ClassTypeUtil.getClass(entity)) >= 1; + } + return save(entity); + } + + protected MutablePair getUpdateCondition(List compareConditionList, T entity){ + BasicDBObject queryBasic = BuildCondition.buildQueryCondition(compareConditionList); + Document document = DocumentUtil.checkUpdateField(entity,false); + document.remove(SqlOperationConstant._ID); + BasicDBObject updateField = new BasicDBObject(SpecialConditionEnum.SET.getCondition(), document); + return new MutablePair<>(queryBasic,updateField); } @Override public Boolean saveOrUpdateBatch(Collection entityList) { - return factory.getExecute(database).saveOrUpdateBatch(entityList); + List> writeModelList = new ArrayList<>(); + entityList.forEach(entity -> { + String idByEntity = ClassTypeUtil.getIdByEntity(entity, true); + if (StringUtils.isBlank(idByEntity)){ + writeModelList.add(new InsertOneModel<>(baseMapper.processIdField(entity,false))); + } else { + MutablePair basicDBObjectPair = getUpdate(entity); + writeModelList.add(new UpdateManyModel<>(basicDBObjectPair.getLeft(),basicDBObjectPair.getRight())); + } + }); + return baseMapper.bulkWrite(writeModelList,entityList.stream().findFirst().get().getClass()) == entityList.size(); + } + + @Override + public Boolean saveOrUpdateBatchWrapper(Collection entityList, QueryChainWrapper queryChainWrapper) { + Class clazz = entityList.stream().findFirst().get().getClass(); + List> writeModelList = new ArrayList<>(); + entityList.forEach(entity -> { + long count = baseMapper.count(queryChainWrapper, clazz); + if (count > 0){ + MutablePair updatePair = getUpdateCondition(queryChainWrapper.getCompareList(), entity); + writeModelList.add(new UpdateManyModel<>(updatePair.getLeft(),updatePair.getRight())); + } else { + writeModelList.add(new InsertOneModel<>(baseMapper.processIdField(entity,false))); + } + }); + return baseMapper.bulkWrite(writeModelList,entityList.stream().findFirst().get().getClass()) == entityList.size(); } @Override public Boolean updateById(T entity) { - return factory.getExecute(database).updateById(entity); + MutablePair basicDBObjectPair = getUpdate(entity); + return baseMapper.update(basicDBObjectPair.getLeft(),basicDBObjectPair.getRight(),ClassTypeUtil.getClass(entity)) >= 1; + } + + protected MutablePair getUpdate(T entity) { + Document document = DocumentUtil.checkUpdateField(entity,false); + BasicDBObject filter = ExecuteUtil.getFilter(document); + BasicDBObject update = new BasicDBObject(SpecialConditionEnum.SET.getCondition(), document); + return new MutablePair<>(filter,update); } @Override public Boolean updateBatchByIds(Collection entityList) { - return factory.getExecute(database).updateBatchByIds(entityList); + List> writeModelList = new ArrayList<>(); + entityList.forEach(entity -> { + MutablePair basicDBObjectPair = getUpdate(entity); + writeModelList.add(new UpdateManyModel<>(basicDBObjectPair.getLeft(),basicDBObjectPair.getRight())); + }); + return baseMapper.bulkWrite(writeModelList,entityList.stream().findFirst().get().getClass()) == entityList.size(); } @Override public Boolean updateByColumn(T entity, SFunction column) { - return factory.getExecute(database).updateByColumn(entity,column); + return updateByColumn(entity,column.getFieldNameLine()); } @Override public Boolean updateByColumn(T entity, String column) { - return factory.getExecute(database).updateByColumn(entity,column); + Object filterValue = ClassTypeUtil.getClassFieldValue(entity,column); + String valueOf = String.valueOf(filterValue); + Bson filter = Filters.eq(column, ObjectId.isValid(valueOf) ? new ObjectId(valueOf) : filterValue); + Document document = DocumentUtil.checkUpdateField(entity,false); + return baseMapper.update(filter,document,ClassTypeUtil.getClass(entity)) >= 1; } @Override public Boolean remove(UpdateChainWrapper updateChainWrapper) { - return factory.getExecute(database).remove(updateChainWrapper.getCompareList(),clazz); + return baseMapper.remove(updateChainWrapper,clazz); } @Override public Boolean update(UpdateChainWrapper updateChainWrapper) { - List compareConditionList = new ArrayList<>(); - compareConditionList.addAll(updateChainWrapper.getCompareList()); - compareConditionList.addAll(updateChainWrapper.getUpdateCompareList()); - return factory.getExecute(database).update(compareConditionList,clazz); + return baseMapper.update(updateChainWrapper,clazz); + } + + @Override + public Boolean update(T entity, QueryChainWrapper queryChainWrapper) { + return baseMapper.update(entity,queryChainWrapper); } @Override public Boolean removeById(Serializable id) { - return factory.getExecute(database).removeById(id,clazz); + Bson filterId = Filters.eq(SqlOperationConstant._ID, ObjectId.isValid(String.valueOf(id)) ? new ObjectId(String.valueOf(id)) : id); + return baseMapper.remove(filterId,clazz) >= 1; } @Override public Boolean removeByColumn(SFunction column, Object value) { - return factory.getExecute(database).removeByColumn(column,value,clazz); + return removeByColumn(column.getFieldNameLine(),value); } @Override public Boolean removeByColumn(String column, Object value) { - return factory.getExecute(database).removeByColumn(column,value,clazz); + Bson filter = Filters.eq(column, ObjectId.isValid(String.valueOf(value)) ? new ObjectId(String.valueOf(value)) : value); + return baseMapper.remove(filter,clazz) >= 1; } @Override public Boolean removeBatchByIds(Collection idList) { - return factory.getExecute(database).removeBatchByIds(idList,clazz); - } - - @Override - public List list() { - return factory.getExecute(database).list(clazz); + List convertedIds = idList.stream() + .map(id -> ObjectId.isValid(String.valueOf(id)) ? new ObjectId(String.valueOf(id)) : id) + .collect(Collectors.toList()); + Bson objectIdBson = Filters.in(SqlOperationConstant._ID, convertedIds); + return baseMapper.remove(objectIdBson,clazz) >= 1; } @Override public List aggregateList(AggregateChainWrapper queryChainWrapper) { - return factory.getExecute(database).aggregateList(queryChainWrapper.getBaseAggregateList(),queryChainWrapper.getBasicDBObjectList(),queryChainWrapper.getOptionsBasicDBObject(),clazz); + return baseMapper.aggregateList(queryChainWrapper,clazz); } @Override public T one(QueryChainWrapper queryChainWrapper) { - return factory.getExecute(database).one(queryChainWrapper.getCompareList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList(),clazz); + return baseMapper.one(queryChainWrapper,clazz); } @Override + @Deprecated public T limitOne(QueryChainWrapper queryChainWrapper) { - return factory.getExecute(database).limitOne(queryChainWrapper.getCompareList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList(),queryChainWrapper.getOrderList(),clazz); + return baseMapper.limitOne(queryChainWrapper,clazz); + } + + @Override + public List list() { + return baseMapper.list(clazz); } @Override public List list(QueryChainWrapper queryChainWrapper) { - return factory.getExecute(database).list(queryChainWrapper.getCompareList(),queryChainWrapper.getOrderList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList(),clazz); + return baseMapper.list(queryChainWrapper,clazz); } @Override public List list(AggregateChainWrapper queryChainWrapper) { - return factory.getExecute(database).aggregateList(queryChainWrapper.getBaseAggregateList(),queryChainWrapper.getBasicDBObjectList(),queryChainWrapper.getOptionsBasicDBObject(),clazz); + return baseMapper.aggregateList(queryChainWrapper,clazz); } @Override public long count() { - return factory.getExecute(database).count(clazz); + return baseMapper.count(clazz); } @Override public long count(QueryChainWrapper queryChainWrapper) { - return factory.getExecute(database).count(queryChainWrapper.getCompareList(),clazz); + return baseMapper.count(queryChainWrapper,clazz); } @Override public PageResult page(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize){ - return factory.getExecute(database).page(queryChainWrapper.getCompareList(),queryChainWrapper.getOrderList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList(), pageNum,pageSize,clazz); + return baseMapper.page(queryChainWrapper, pageNum,pageSize,clazz); } @Override public PageResult page(QueryChainWrapper queryChainWrapper, PageParam pageParam) { - return factory.getExecute(database).page(queryChainWrapper.getCompareList(),queryChainWrapper.getOrderList(),queryChainWrapper.getProjectionList(),queryChainWrapper.getBasicDBObjectList(),pageParam.getPageNum(),pageParam.getPageSize(),clazz); + return page(queryChainWrapper,pageParam.getPageNum(),pageParam.getPageSize()); + } + + @Override + public PageResult page(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize, Integer recentPageNum){ + return baseMapper.page(queryChainWrapper, pageNum,pageSize,recentPageNum,clazz); + } + + @Override + public PageResult page(QueryChainWrapper queryChainWrapper, PageParam pageParam, Integer recentPageNum) { + return page(queryChainWrapper,pageParam.getPageNum(),pageParam.getPageSize(),recentPageNum); + } + + @Override + public List pageList(PageParam pageParam) { + return pageList(pageParam.getPageNum(),pageParam.getPageSize()); + } + + @Override + public List pageList(Integer pageNum, Integer pageSize) { + return baseMapper.pageList(new QueryWrapper<>(),pageNum,pageSize,clazz); + } + + @Override + public List pageList(QueryChainWrapper queryChainWrapper, Integer pageNum, Integer pageSize) { + return baseMapper.pageList(queryChainWrapper,pageNum,pageSize,clazz); + } + + @Override + public List pageList(QueryChainWrapper queryChainWrapper, PageParam pageParam) { + return baseMapper.pageList(queryChainWrapper,pageParam.getPageNum(),pageParam.getPageSize(),clazz); } @Override @@ -225,89 +325,109 @@ public class ServiceImpl implements IService{ return page(pageParam.getPageNum(),pageParam.getPageSize()); } + @Override + public PageResult page(PageParam pageParam, Integer recentPageNum) { + return page(pageParam.getPageNum(), pageParam.getPageSize(), recentPageNum); + } + @Override public PageResult page(Integer pageNum, Integer pageSize) { - return factory.getExecute(database).page(null,null,null,null,pageNum,pageSize,clazz); + return page(new QueryWrapper<>(),pageNum,pageSize); + } + + @Override + public PageResult page(Integer pageNum, Integer pageSize, Integer recentPageNum) { + return baseMapper.page(new QueryWrapper<>(),pageNum,pageSize,recentPageNum,clazz); } @Override public T getById(Serializable id) { - return factory.getExecute(database).getById(id,clazz); + return baseMapper.getById(id,clazz); } @Override public List getByIds(Collection ids) { - return factory.getExecute(database).getByIds(ids,clazz); + return baseMapper.getByIds(ids,clazz); } @Override public List queryCommand(String command) { - return factory.getExecute(database).queryCommand(command,clazz); + return baseMapper.queryCommand(command,clazz); } @Override public List getByColumn(SFunction field, Object fieldValue) { - return factory.getExecute(database).getByColumn(field.getFieldNameLine(), fieldValue,clazz); + return baseMapper.getByColumn(field.getFieldNameLine(), fieldValue,clazz); } @Override public List getByColumn(String field, Object fieldValue) { - return factory.getExecute(database).getByColumn(field,fieldValue,clazz); + return baseMapper.getByColumn(field,fieldValue,clazz); + } + + @Override + public Boolean exist(Serializable id) { + return baseMapper.isExist(id,clazz); + } + + @Override + public Boolean exist(QueryChainWrapper queryChainWrapper) { + return baseMapper.isExist(queryChainWrapper,clazz); } @Override public String createIndex(Bson bson) { - return factory.getExecute(database).createIndex(bson,clazz); + return baseMapper.createIndex(bson,clazz); } @Override public String createIndex(Bson bson, IndexOptions indexOptions) { - return factory.getExecute(database).createIndex(bson,indexOptions,clazz); + return baseMapper.createIndex(bson,indexOptions,clazz); } @Override public List createIndexes(List indexes) { - return factory.getExecute(database).createIndexes(indexes,clazz); + return baseMapper.createIndexes(indexes,clazz); } @Override public List createIndexes(List indexes, CreateIndexOptions createIndexOptions) { - return factory.getExecute(database).createIndexes(indexes,createIndexOptions,clazz); + return baseMapper.createIndexes(indexes,createIndexOptions,clazz); } @Override public List listIndexes() { - return factory.getExecute(database).listIndexes(clazz); + return baseMapper.listIndexes(clazz); } @Override public void dropIndex(String indexName) { - factory.getExecute(database).dropIndex(indexName,clazz); + baseMapper.dropIndex(indexName,clazz); } @Override public void dropIndex(String indexName, DropIndexOptions dropIndexOptions) { - factory.getExecute(database).dropIndex(indexName,dropIndexOptions,clazz); + baseMapper.dropIndex(indexName,dropIndexOptions,clazz); } @Override public void dropIndex(Bson keys) { - factory.getExecute(database).dropIndex(keys,clazz); + baseMapper.dropIndex(keys,clazz); } @Override public void dropIndex(Bson keys, DropIndexOptions dropIndexOptions) { - factory.getExecute(database).dropIndex(keys,dropIndexOptions,clazz); + baseMapper.dropIndex(keys,dropIndexOptions,clazz); } @Override public void dropIndexes() { - factory.getExecute(database).dropIndexes(clazz); + baseMapper.dropIndexes(clazz); } @Override public void dropIndexes(DropIndexOptions dropIndexOptions) { - factory.getExecute(database).dropIndexes(dropIndexOptions,clazz); + baseMapper.dropIndexes(dropIndexOptions,clazz); } public Class getClazz() { @@ -316,16 +436,16 @@ public class ServiceImpl implements IService{ @Override public LambdaQueryChainWrapper lambdaQuery() { - return ChainWrappers.lambdaQueryChain(factory,clazz,database); + return ChainWrappers.lambdaQueryChain(baseMapper,clazz); } @Override public LambdaAggregateChainWrapper lambdaAggregate() { - return ChainWrappers.lambdaAggregateChain(factory,clazz,database); + return ChainWrappers.lambdaAggregateChain(baseMapper,clazz); } @Override public LambdaUpdateChainWrapper lambdaUpdate() { - return ChainWrappers.lambdaUpdateChain(factory,clazz,database); + return ChainWrappers.lambdaUpdateChain(baseMapper,clazz); } } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/strategy/aggregate/impl/SortConcretePipeline.java b/mongo-plus-core/src/main/java/com/anwen/mongo/strategy/aggregate/impl/SortConcretePipeline.java index 92ff600eba342894925524835e195386f69f523f..930142fb401b81e20022b18f1d73dd4dc907724b 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/strategy/aggregate/impl/SortConcretePipeline.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/strategy/aggregate/impl/SortConcretePipeline.java @@ -1,6 +1,6 @@ package com.anwen.mongo.strategy.aggregate.impl; -import com.anwen.mongo.conditions.MongoPlusBasicDBObject; +import com.anwen.mongo.bson.MongoPlusBasicDBObject; import com.anwen.mongo.conditions.interfaces.condition.Order; import com.anwen.mongo.strategy.aggregate.PipelineStrategy; import com.mongodb.BasicDBObject; diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/strategy/convert/impl/StringConversionStrategy.java b/mongo-plus-core/src/main/java/com/anwen/mongo/strategy/convert/impl/StringConversionStrategy.java index 56d1148b58feec30b6b148cf3595c50828fd398c..0e873e9de98666a6129ddd1115601ab78cba89ad 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/strategy/convert/impl/StringConversionStrategy.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/strategy/convert/impl/StringConversionStrategy.java @@ -1,7 +1,6 @@ package com.anwen.mongo.strategy.convert.impl; import com.anwen.mongo.strategy.convert.ConversionStrategy; -import com.anwen.mongo.toolkit.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,12 +17,17 @@ public class StringConversionStrategy implements ConversionStrategy { @Override public String convertValue(Field field, Object obj, Object fieldValue) throws IllegalAccessException { - String value = null; try { - value = StringUtils.isNotBlankAndConvert(fieldValue); + if (fieldValue == null) { + return null; + } + if (fieldValue instanceof String) { + return (String) fieldValue; + } + return String.valueOf(fieldValue); } catch (Exception e) { logger.error("Conversion to String failed, exception message: {}",e.getMessage()); } - return value; + return null; } } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/ArrayUtils.java b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/ArrayUtils.java index 785f1d32f3046c45a796574bccbe122c8f6dd4b6..e1f1b8583f7e34d1fbeb3c3e33fd7bbcdb4e27a8 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/ArrayUtils.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/ArrayUtils.java @@ -10,6 +10,10 @@ package com.anwen.mongo.toolkit; */ public final class ArrayUtils { + public static final int INDEX_NOT_FOUND = -1; + + public static final String[] EMPTY_STRING_ARRAY = new String[0]; + private ArrayUtils() { } @@ -34,4 +38,35 @@ public final class ArrayUtils { return !isEmpty(array); } + public static boolean contains(final Object[] array, final Object objectToFind) { + return indexOf(array, objectToFind) != INDEX_NOT_FOUND; + } + + public static int indexOf(final Object[] array, final Object objectToFind) { + return indexOf(array, objectToFind, 0); + } + + public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) { + if (array == null) { + return INDEX_NOT_FOUND; + } + if (startIndex < 0) { + startIndex = 0; + } + if (objectToFind == null) { + for (int i = startIndex; i < array.length; i++) { + if (array[i] == null) { + return i; + } + } + } else if (array.getClass().getComponentType().isInstance(objectToFind)) { + for (int i = startIndex; i < array.length; i++) { + if (objectToFind.equals(array[i])) { + return i; + } + } + } + return INDEX_NOT_FOUND; + } + } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/ChainWrappers.java b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/ChainWrappers.java index 8e0c3fb77d14823c5471c847e70155dae03fe875..9f3d2fe2f5284daa516b5a68c7db473ffced80bc 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/ChainWrappers.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/ChainWrappers.java @@ -12,7 +12,7 @@ import com.anwen.mongo.conditions.query.QueryWrapper; import com.anwen.mongo.conditions.update.LambdaUpdateChainWrapper; import com.anwen.mongo.conditions.update.UpdateChainWrapper; import com.anwen.mongo.conditions.update.UpdateWrapper; -import com.anwen.mongo.execute.ExecutorFactory; +import com.anwen.mongo.mapper.BaseMapper; import java.util.Map; @@ -23,16 +23,16 @@ import java.util.Map; */ public final class ChainWrappers { - public static LambdaQueryChainWrapper lambdaQueryChain(ExecutorFactory factory, Class clazz,String database){ - return new LambdaQueryChainWrapper<>(factory, clazz,database); + public static LambdaQueryChainWrapper lambdaQueryChain(BaseMapper baseMapper, Class clazz){ + return new LambdaQueryChainWrapper<>(baseMapper, clazz); } - public static LambdaAggregateChainWrapper lambdaAggregateChain(ExecutorFactory factory,Class clazz,String database){ - return new LambdaAggregateChainWrapper<>(factory,clazz,database); + public static LambdaAggregateChainWrapper lambdaAggregateChain(BaseMapper baseMapper, Class clazz){ + return new LambdaAggregateChainWrapper<>(baseMapper, clazz); } - public static LambdaUpdateChainWrapper lambdaUpdateChain(ExecutorFactory factory,Class clazz,String database){ - return new LambdaUpdateChainWrapper<>(factory,clazz,database); + public static LambdaUpdateChainWrapper lambdaUpdateChain(BaseMapper baseMapper, Class clazz){ + return new LambdaUpdateChainWrapper<>(baseMapper, clazz); } public static UpdateChainWrapper> lambdaUpdateChain(){ @@ -44,11 +44,11 @@ public final class ChainWrappers { } public static QueryChainWrapper> lambdaQueryChain(){ - return new QueryChainWrapper<>(); + return new QueryWrapper<>(); } public static QueryChainWrapper, InjectQueryWrapper> lambdaQueryChainInject(){ - return new QueryChainWrapper<>(); + return new InjectQueryWrapper(); } public static AggregateChainWrapper> lambdaAggregateChain(){ diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/InstantUtil.java b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/InstantUtil.java index 17219408199d500ba35adcfdff503aa06a454b6e..3948b79b857949b147689b8e2203aa2e519b209e 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/InstantUtil.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/InstantUtil.java @@ -29,11 +29,11 @@ public class InstantUtil { logger.error("Convert To Instant Fail,message: {}",e.getMessage(),e); throw new MongoException("Convert To Instant Fail"); } - return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()).minusHours(8); + return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); } public static LocalDateTime convertTimestampToLocalDateTime(Instant instant){ - return LocalDateTime.ofInstant(instant,ZoneId.systemDefault()).minusHours(8); + return LocalDateTime.ofInstant(instant,ZoneId.systemDefault()); } /** diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/LambdaOperate.java b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/LambdaOperate.java index afed057bb6b5d9a597b419c68efbdc32720f071b..7e11eda14e3afe00183e31cc55bca077c3136edc 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/LambdaOperate.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/LambdaOperate.java @@ -11,6 +11,7 @@ import com.anwen.mongo.model.PageParam; import com.anwen.mongo.model.PageResult; import com.mongodb.BasicDBObject; import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCursor; import org.bson.Document; import java.util.List; @@ -29,6 +30,12 @@ public class LambdaOperate { return DocumentMapperConvert.mapDocumentList(iterable, clazz); } + public T getLambdaQueryResultOne(FindIterable iterable, Class clazz) { + try (MongoCursor cursor = iterable.iterator()) { + return DocumentMapperConvert.mapDocument(cursor.next(), clazz); + } + } + public List> getLambdaQueryResult(FindIterable iterable,Integer size) { return Converter.convertDocumentToMap(iterable,size); } @@ -51,9 +58,13 @@ public class LambdaOperate { PageResult pageResult = new PageResult<>(); pageResult.setPageNum(pageParams.getPageNum()); pageResult.setPageSize(pageParams.getPageSize()); + pageResult.setContentData(DocumentMapperConvert.mapDocumentList(documentFindIterable.skip((pageParams.getPageNum() - 1) * pageParams.getPageSize()).limit(pageParams.getPageSize()), clazz)); + // 不查询总条数,总条数=当前页的总数 + if (totalSize == -1) { + totalSize = pageResult.getContentData().size(); + } pageResult.setTotalSize(totalSize); pageResult.setTotalPages((totalSize + pageParams.getPageSize() - 1) / pageParams.getPageSize()); - pageResult.setContentData(DocumentMapperConvert.mapDocumentList(documentFindIterable.skip((pageParams.getPageNum() - 1) * pageParams.getPageSize()).limit(pageParams.getPageSize()), clazz)); return pageResult; } diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/StringUtils.java b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/StringUtils.java index 83f80ef2ed0995567bc6b54b5f0ac262cedc8557..f90fa0ab7185eca77afe505bed7e405032d3416a 100644 --- a/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/StringUtils.java +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/StringUtils.java @@ -118,6 +118,9 @@ public final class StringUtils { if (str == null) { return true; } + if (str.equals("null")){ + return true; + } int len = str.length(); if (len == 0) { return true; diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/builder/Builder.java b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/builder/Builder.java new file mode 100644 index 0000000000000000000000000000000000000000..a63b483011dd0b1ecadeeb855f3380483f3923c7 --- /dev/null +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/builder/Builder.java @@ -0,0 +1,19 @@ +package com.anwen.mongo.toolkit.builder; + +/** + * 生成器接口用于在生成器设计模式中将类指定为生成器对象。构建器能够创建和配置对象或结果,这些对象或结果通常需要多个步骤才能构建,或者派生起来非常复杂。 + * 生成器接口定义了类必须实现的单个方法build()。此方法的结果应该是执行所有构建操作后的最终配置对象或结果。 + * 建议使用为配置正在构建的对象或结果而提供的方法返回对此的引用,以便将方法调用链接在一起。 + * @author JiaChaoYang + * @date 2024/3/16 22:41 +*/ +public interface Builder { + + /** + * 返回对构建器正在构建的对象或正在计算的结果的引用。 + * @author JiaChaoYang + * @date 2024/3/16 22:41 + */ + T build(); + +} diff --git a/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/builder/CompareToBuilder.java b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/builder/CompareToBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..c5d9a425e387b9f2d45c1f5056017bd3d4ad942c --- /dev/null +++ b/mongo-plus-core/src/main/java/com/anwen/mongo/toolkit/builder/CompareToBuilder.java @@ -0,0 +1,986 @@ +package com.anwen.mongo.toolkit.builder; + +import com.anwen.mongo.toolkit.ArrayUtils; + +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; + +/** + * 协助实现Comparable.compareTo(Object)方法。 + * 它与EqualsBuilder和HashCodeBuilder构建的equals(Object)和hashcode()一致。 + * 使用equals(Object)比较相等的两个对象通常也应使用compareTo(Object)进行相等比较。 + * 所有相关字段都应包括在比较的计算中。派生字段可能会被忽略。compareTo(Object)和equals(Object)中应以相同的顺序使用相同的字段。 + * 要使用此类,请编写以下代码: + * 公共类MyClass{ + * 字符串字段1; + * int字段2; + * 布尔字段3; + * ... + * public int compareTo(对象o){ + * MyClass MyClass=(MyClass)o; + * 返回new CompareToBuilder() + * .appendSuper(super.compareTo(o) + * .append(this.field1,myClass.field1) + * .append(this.field2,myClass.field2) + * .append(this.field3,myClass.field3) + * .toComparison(); + * } + * } + * 或者,也有使用反射的reflectionCompare方法 + * @author JiaChaoYang + **/ +public class CompareToBuilder implements Builder { + /** + * Current state of the comparison as appended fields are checked. + */ + private int comparison; + + /** + *

Constructor for CompareToBuilder.

+ * + *

Starts off assuming that the objects are equal. Multiple calls are + * then made to the various append methods, followed by a call to + * {@link #toComparison} to get the result.

+ */ + public CompareToBuilder() { + super(); + comparison = 0; + } + + //----------------------------------------------------------------------- + /** + *

Compares two Objects via reflection.

+ * + *

Fields can be private, thus AccessibleObject.setAccessible + * is used to bypass normal access control checks. This will fail under a + * security manager unless the appropriate permissions are set.

+ * + *
    + *
  • Static fields will not be compared
  • + *
  • Transient members will be not be compared, as they are likely derived + * fields
  • + *
  • Superclass fields will be compared
  • + *
+ * + *

If both lhs and rhs are null, + * they are considered equal.

+ * + * @param lhs left-hand object + * @param rhs right-hand object + * @return a negative integer, zero, or a positive integer as lhs + * is less than, equal to, or greater than rhs + * @throws NullPointerException if either (but not both) parameters are + * null + * @throws ClassCastException if rhs is not assignment-compatible + * with lhs + */ + public static int reflectionCompare(final Object lhs, final Object rhs) { + return reflectionCompare(lhs, rhs, false, null); + } + + /** + *

Compares two Objects via reflection.

+ * + *

Fields can be private, thus AccessibleObject.setAccessible + * is used to bypass normal access control checks. This will fail under a + * security manager unless the appropriate permissions are set.

+ * + *
    + *
  • Static fields will not be compared
  • + *
  • If compareTransients is true, + * compares transient members. Otherwise ignores them, as they + * are likely derived fields.
  • + *
  • Superclass fields will be compared
  • + *
+ * + *

If both lhs and rhs are null, + * they are considered equal.

+ * + * @param lhs left-hand object + * @param rhs right-hand object + * @param compareTransients whether to compare transient fields + * @return a negative integer, zero, or a positive integer as lhs + * is less than, equal to, or greater than rhs + * @throws NullPointerException if either lhs or rhs + * (but not both) is null + * @throws ClassCastException if rhs is not assignment-compatible + * with lhs + */ + public static int reflectionCompare(final Object lhs, final Object rhs, final boolean compareTransients) { + return reflectionCompare(lhs, rhs, compareTransients, null); + } + + /** + *

Compares two Objects via reflection.

+ * + *

Fields can be private, thus AccessibleObject.setAccessible + * is used to bypass normal access control checks. This will fail under a + * security manager unless the appropriate permissions are set.

+ * + *
    + *
  • Static fields will not be compared
  • + *
  • If compareTransients is true, + * compares transient members. Otherwise ignores them, as they + * are likely derived fields.
  • + *
  • Superclass fields will be compared
  • + *
+ * + *

If both lhs and rhs are null, + * they are considered equal.

+ * + * @param lhs left-hand object + * @param rhs right-hand object + * @param excludeFields Collection of String fields to exclude + * @return a negative integer, zero, or a positive integer as lhs + * is less than, equal to, or greater than rhs + * @throws NullPointerException if either lhs or rhs + * (but not both) is null + * @throws ClassCastException if rhs is not assignment-compatible + * with lhs + * @since 2.2 + */ + public static int reflectionCompare(final Object lhs, final Object rhs, final Collection excludeFields) { + return reflectionCompare(lhs, rhs, toNoNullStringArray(excludeFields)); + } + + /** + *

Compares two Objects via reflection.

+ * + *

Fields can be private, thus AccessibleObject.setAccessible + * is used to bypass normal access control checks. This will fail under a + * security manager unless the appropriate permissions are set.

+ * + *
    + *
  • Static fields will not be compared
  • + *
  • If compareTransients is true, + * compares transient members. Otherwise ignores them, as they + * are likely derived fields.
  • + *
  • Superclass fields will be compared
  • + *
+ * + *

If both lhs and rhs are null, + * they are considered equal.

+ * + * @param lhs left-hand object + * @param rhs right-hand object + * @param excludeFields array of fields to exclude + * @return a negative integer, zero, or a positive integer as lhs + * is less than, equal to, or greater than rhs + * @throws NullPointerException if either lhs or rhs + * (but not both) is null + * @throws ClassCastException if rhs is not assignment-compatible + * with lhs + * @since 2.2 + */ + public static int reflectionCompare(final Object lhs, final Object rhs, final String... excludeFields) { + return reflectionCompare(lhs, rhs, false, null, excludeFields); + } + + /** + *

Compares two Objects via reflection.

+ * + *

Fields can be private, thus AccessibleObject.setAccessible + * is used to bypass normal access control checks. This will fail under a + * security manager unless the appropriate permissions are set.

+ * + *
    + *
  • Static fields will not be compared
  • + *
  • If the compareTransients is true, + * compares transient members. Otherwise ignores them, as they + * are likely derived fields.
  • + *
  • Compares superclass fields up to and including reflectUpToClass. + * If reflectUpToClass is null, compares all superclass fields.
  • + *
+ * + *

If both lhs and rhs are null, + * they are considered equal.

+ * + * @param lhs left-hand object + * @param rhs right-hand object + * @param compareTransients whether to compare transient fields + * @param reflectUpToClass last superclass for which fields are compared + * @param excludeFields fields to exclude + * @return a negative integer, zero, or a positive integer as lhs + * is less than, equal to, or greater than rhs + * @throws NullPointerException if either lhs or rhs + * (but not both) is null + * @throws ClassCastException if rhs is not assignment-compatible + * with lhs + * @since 2.2 (2.0 as reflectionCompare(Object, Object, boolean, Class)) + */ + public static int reflectionCompare( + final Object lhs, + final Object rhs, + final boolean compareTransients, + final Class reflectUpToClass, + final String... excludeFields) { + + if (lhs == rhs) { + return 0; + } + if (lhs == null || rhs == null) { + throw new NullPointerException(); + } + Class lhsClazz = lhs.getClass(); + if (!lhsClazz.isInstance(rhs)) { + throw new ClassCastException(); + } + final CompareToBuilder compareToBuilder = new CompareToBuilder(); + reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients, excludeFields); + while (lhsClazz.getSuperclass() != null && lhsClazz != reflectUpToClass) { + lhsClazz = lhsClazz.getSuperclass(); + reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients, excludeFields); + } + return compareToBuilder.toComparison(); + } + + /** + *

Appends to builder the comparison of lhs + * to rhs using the fields defined in clazz.

+ * + * @param lhs left-hand object + * @param rhs right-hand object + * @param clazz Class that defines fields to be compared + * @param builder CompareToBuilder to append to + * @param useTransients whether to compare transient fields + * @param excludeFields fields to exclude + */ + private static void reflectionAppend( + final Object lhs, + final Object rhs, + final Class clazz, + final CompareToBuilder builder, + final boolean useTransients, + final String[] excludeFields) { + + final Field[] fields = clazz.getDeclaredFields(); + AccessibleObject.setAccessible(fields, true); + for (int i = 0; i < fields.length && builder.comparison == 0; i++) { + final Field f = fields[i]; + if (!ArrayUtils.contains(excludeFields, f.getName()) + && (f.getName().indexOf('$') == -1) + && (useTransients || !Modifier.isTransient(f.getModifiers())) + && (!Modifier.isStatic(f.getModifiers()))) { + try { + builder.append(f.get(lhs), f.get(rhs)); + } catch (final IllegalAccessException e) { + // This can't happen. Would get a Security exception instead. + // Throw a runtime exception in case the impossible happens. + throw new InternalError("Unexpected IllegalAccessException"); + } + } + } + } + + //----------------------------------------------------------------------- + /** + *

Appends to the builder the compareTo(Object) + * result of the superclass.

+ * + * @param superCompareTo result of calling super.compareTo(Object) + * @return this - used to chain append calls + * @since 2.0 + */ + public CompareToBuilder appendSuper(final int superCompareTo) { + if (comparison != 0) { + return this; + } + comparison = superCompareTo; + return this; + } + + //----------------------------------------------------------------------- + /** + *

Appends to the builder the comparison of + * two Objects.

+ * + *
    + *
  1. Check if lhs == rhs
  2. + *
  3. Check if either lhs or rhs is null, + * a null object is less than a non-null object
  4. + *
  5. Check the object contents
  6. + *
+ * + *

lhs must either be an array or implement {@link Comparable}.

+ * + * @param lhs left-hand object + * @param rhs right-hand object + * @return this - used to chain append calls + * @throws ClassCastException if rhs is not assignment-compatible + * with lhs + */ + public CompareToBuilder append(final Object lhs, final Object rhs) { + return append(lhs, rhs, null); + } + + /** + *

Appends to the builder the comparison of + * two Objects.

+ * + *
    + *
  1. Check if lhs == rhs
  2. + *
  3. Check if either lhs or rhs is null, + * a null object is less than a non-null object
  4. + *
  5. Check the object contents
  6. + *
+ * + *

If lhs is an array, array comparison methods will be used. + * Otherwise comparator will be used to compare the objects. + * If comparator is null, lhs must + * implement {@link Comparable} instead.

+ * + * @param lhs left-hand object + * @param rhs right-hand object + * @param comparator Comparator used to compare the objects, + * null means treat lhs as Comparable + * @return this - used to chain append calls + * @throws ClassCastException if rhs is not assignment-compatible + * with lhs + * @since 2.0 + */ + public CompareToBuilder append(final Object lhs, final Object rhs, final Comparator comparator) { + if (comparison != 0) { + return this; + } + if (lhs == rhs) { + return this; + } + if (lhs == null) { + comparison = -1; + return this; + } + if (rhs == null) { + comparison = +1; + return this; + } + if (lhs.getClass().isArray()) { + // switch on type of array, to dispatch to the correct handler + // handles multi dimensional arrays + // throws a ClassCastException if rhs is not the correct array type + if (lhs instanceof long[]) { + append((long[]) lhs, (long[]) rhs); + } else if (lhs instanceof int[]) { + append((int[]) lhs, (int[]) rhs); + } else if (lhs instanceof short[]) { + append((short[]) lhs, (short[]) rhs); + } else if (lhs instanceof char[]) { + append((char[]) lhs, (char[]) rhs); + } else if (lhs instanceof byte[]) { + append((byte[]) lhs, (byte[]) rhs); + } else if (lhs instanceof double[]) { + append((double[]) lhs, (double[]) rhs); + } else if (lhs instanceof float[]) { + append((float[]) lhs, (float[]) rhs); + } else if (lhs instanceof boolean[]) { + append((boolean[]) lhs, (boolean[]) rhs); + } else { + // not an array of primitives + // throws a ClassCastException if rhs is not an array + append((Object[]) lhs, (Object[]) rhs, comparator); + } + } else { + // the simple case, not an array, just test the element + if (comparator == null) { + @SuppressWarnings("unchecked") // assume this can be done; if not throw CCE as per Javadoc + final Comparable comparable = (Comparable) lhs; + comparison = comparable.compareTo(rhs); + } else { + @SuppressWarnings("unchecked") // assume this can be done; if not throw CCE as per Javadoc + final Comparator comparator2 = (Comparator) comparator; + comparison = comparator2.compare(lhs, rhs); + } + } + return this; + } + + //------------------------------------------------------------------------- + /** + * Appends to the builder the comparison of + * two longs. + * + * @param lhs left-hand value + * @param rhs right-hand value + * @return this - used to chain append calls + */ + public CompareToBuilder append(final long lhs, final long rhs) { + if (comparison != 0) { + return this; + } + comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0)); + return this; + } + + /** + * Appends to the builder the comparison of + * two ints. + * + * @param lhs left-hand value + * @param rhs right-hand value + * @return this - used to chain append calls + */ + public CompareToBuilder append(final int lhs, final int rhs) { + if (comparison != 0) { + return this; + } + comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0)); + return this; + } + + /** + * Appends to the builder the comparison of + * two shorts. + * + * @param lhs left-hand value + * @param rhs right-hand value + * @return this - used to chain append calls + */ + public CompareToBuilder append(final short lhs, final short rhs) { + if (comparison != 0) { + return this; + } + comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0)); + return this; + } + + /** + * Appends to the builder the comparison of + * two chars. + * + * @param lhs left-hand value + * @param rhs right-hand value + * @return this - used to chain append calls + */ + public CompareToBuilder append(final char lhs, final char rhs) { + if (comparison != 0) { + return this; + } + comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0)); + return this; + } + + /** + * Appends to the builder the comparison of + * two bytes. + * + * @param lhs left-hand value + * @param rhs right-hand value + * @return this - used to chain append calls + */ + public CompareToBuilder append(final byte lhs, final byte rhs) { + if (comparison != 0) { + return this; + } + comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0)); + return this; + } + + /** + *

Appends to the builder the comparison of + * two doubles.

+ * + *

This handles NaNs, Infinities, and -0.0.

+ * + *

It is compatible with the hash code generated by + * HashCodeBuilder.

+ * + * @param lhs left-hand value + * @param rhs right-hand value + * @return this - used to chain append calls + */ + public CompareToBuilder append(final double lhs, final double rhs) { + if (comparison != 0) { + return this; + } + comparison = Double.compare(lhs, rhs); + return this; + } + + /** + *

Appends to the builder the comparison of + * two floats.

+ * + *

This handles NaNs, Infinities, and -0.0.

+ * + *

It is compatible with the hash code generated by + * HashCodeBuilder.

+ * + * @param lhs left-hand value + * @param rhs right-hand value + * @return this - used to chain append calls + */ + public CompareToBuilder append(final float lhs, final float rhs) { + if (comparison != 0) { + return this; + } + comparison = Float.compare(lhs, rhs); + return this; + } + + /** + * Appends to the builder the comparison of + * two booleanss. + * + * @param lhs left-hand value + * @param rhs right-hand value + * @return this - used to chain append calls + */ + public CompareToBuilder append(final boolean lhs, final boolean rhs) { + if (comparison != 0) { + return this; + } + if (lhs == rhs) { + return this; + } + if (lhs == false) { + comparison = -1; + } else { + comparison = +1; + } + return this; + } + + //----------------------------------------------------------------------- + /** + *

Appends to the builder the deep comparison of + * two Object arrays.

+ * + *
    + *
  1. Check if arrays are the same using ==
  2. + *
  3. Check if for null, null is less than non-null
  4. + *
  5. Check array length, a short length array is less than a long length array
  6. + *
  7. Check array contents element by element using {@link #append(Object, Object, Comparator)}
  8. + *
+ * + *

This method will also will be called for the top level of multi-dimensional, + * ragged, and multi-typed arrays.

+ * + * @param lhs left-hand array + * @param rhs right-hand array + * @return this - used to chain append calls + * @throws ClassCastException if rhs is not assignment-compatible + * with lhs + */ + public CompareToBuilder append(final Object[] lhs, final Object[] rhs) { + return append(lhs, rhs, null); + } + + /** + *

Appends to the builder the deep comparison of + * two Object arrays.

+ * + *
    + *
  1. Check if arrays are the same using ==
  2. + *
  3. Check if for null, null is less than non-null
  4. + *
  5. Check array length, a short length array is less than a long length array
  6. + *
  7. Check array contents element by element using {@link #append(Object, Object, Comparator)}
  8. + *
+ * + *

This method will also will be called for the top level of multi-dimensional, + * ragged, and multi-typed arrays.

+ * + * @param lhs left-hand array + * @param rhs right-hand array + * @param comparator Comparator to use to compare the array elements, + * null means to treat lhs elements as Comparable. + * @return this - used to chain append calls + * @throws ClassCastException if rhs is not assignment-compatible + * with lhs + * @since 2.0 + */ + public CompareToBuilder append(final Object[] lhs, final Object[] rhs, final Comparator comparator) { + if (comparison != 0) { + return this; + } + if (lhs == rhs) { + return this; + } + if (lhs == null) { + comparison = -1; + return this; + } + if (rhs == null) { + comparison = +1; + return this; + } + if (lhs.length != rhs.length) { + comparison = (lhs.length < rhs.length) ? -1 : +1; + return this; + } + for (int i = 0; i < lhs.length && comparison == 0; i++) { + append(lhs[i], rhs[i], comparator); + } + return this; + } + + /** + *

Appends to the builder the deep comparison of + * two long arrays.

+ * + *
    + *
  1. Check if arrays are the same using ==
  2. + *
  3. Check if for null, null is less than non-null
  4. + *
  5. Check array length, a shorter length array is less than a longer length array
  6. + *
  7. Check array contents element by element using {@link #append(long, long)}
  8. + *
+ * + * @param lhs left-hand array + * @param rhs right-hand array + * @return this - used to chain append calls + */ + public CompareToBuilder append(final long[] lhs, final long[] rhs) { + if (comparison != 0) { + return this; + } + if (lhs == rhs) { + return this; + } + if (lhs == null) { + comparison = -1; + return this; + } + if (rhs == null) { + comparison = +1; + return this; + } + if (lhs.length != rhs.length) { + comparison = (lhs.length < rhs.length) ? -1 : +1; + return this; + } + for (int i = 0; i < lhs.length && comparison == 0; i++) { + append(lhs[i], rhs[i]); + } + return this; + } + + /** + *

Appends to the builder the deep comparison of + * two int arrays.

+ * + *
    + *
  1. Check if arrays are the same using ==
  2. + *
  3. Check if for null, null is less than non-null
  4. + *
  5. Check array length, a shorter length array is less than a longer length array
  6. + *
  7. Check array contents element by element using {@link #append(int, int)}
  8. + *
+ * + * @param lhs left-hand array + * @param rhs right-hand array + * @return this - used to chain append calls + */ + public CompareToBuilder append(final int[] lhs, final int[] rhs) { + if (comparison != 0) { + return this; + } + if (lhs == rhs) { + return this; + } + if (lhs == null) { + comparison = -1; + return this; + } + if (rhs == null) { + comparison = +1; + return this; + } + if (lhs.length != rhs.length) { + comparison = (lhs.length < rhs.length) ? -1 : +1; + return this; + } + for (int i = 0; i < lhs.length && comparison == 0; i++) { + append(lhs[i], rhs[i]); + } + return this; + } + + /** + *

Appends to the builder the deep comparison of + * two short arrays.

+ * + *
    + *
  1. Check if arrays are the same using ==
  2. + *
  3. Check if for null, null is less than non-null
  4. + *
  5. Check array length, a shorter length array is less than a longer length array
  6. + *
  7. Check array contents element by element using {@link #append(short, short)}
  8. + *
+ * + * @param lhs left-hand array + * @param rhs right-hand array + * @return this - used to chain append calls + */ + public CompareToBuilder append(final short[] lhs, final short[] rhs) { + if (comparison != 0) { + return this; + } + if (lhs == rhs) { + return this; + } + if (lhs == null) { + comparison = -1; + return this; + } + if (rhs == null) { + comparison = +1; + return this; + } + if (lhs.length != rhs.length) { + comparison = (lhs.length < rhs.length) ? -1 : +1; + return this; + } + for (int i = 0; i < lhs.length && comparison == 0; i++) { + append(lhs[i], rhs[i]); + } + return this; + } + + /** + *

Appends to the builder the deep comparison of + * two char arrays.

+ * + *
    + *
  1. Check if arrays are the same using ==
  2. + *
  3. Check if for null, null is less than non-null
  4. + *
  5. Check array length, a shorter length array is less than a longer length array
  6. + *
  7. Check array contents element by element using {@link #append(char, char)}
  8. + *
+ * + * @param lhs left-hand array + * @param rhs right-hand array + * @return this - used to chain append calls + */ + public CompareToBuilder append(final char[] lhs, final char[] rhs) { + if (comparison != 0) { + return this; + } + if (lhs == rhs) { + return this; + } + if (lhs == null) { + comparison = -1; + return this; + } + if (rhs == null) { + comparison = +1; + return this; + } + if (lhs.length != rhs.length) { + comparison = (lhs.length < rhs.length) ? -1 : +1; + return this; + } + for (int i = 0; i < lhs.length && comparison == 0; i++) { + append(lhs[i], rhs[i]); + } + return this; + } + + /** + *

Appends to the builder the deep comparison of + * two byte arrays.

+ * + *
    + *
  1. Check if arrays are the same using ==
  2. + *
  3. Check if for null, null is less than non-null
  4. + *
  5. Check array length, a shorter length array is less than a longer length array
  6. + *
  7. Check array contents element by element using {@link #append(byte, byte)}
  8. + *
+ * + * @param lhs left-hand array + * @param rhs right-hand array + * @return this - used to chain append calls + */ + public CompareToBuilder append(final byte[] lhs, final byte[] rhs) { + if (comparison != 0) { + return this; + } + if (lhs == rhs) { + return this; + } + if (lhs == null) { + comparison = -1; + return this; + } + if (rhs == null) { + comparison = +1; + return this; + } + if (lhs.length != rhs.length) { + comparison = (lhs.length < rhs.length) ? -1 : +1; + return this; + } + for (int i = 0; i < lhs.length && comparison == 0; i++) { + append(lhs[i], rhs[i]); + } + return this; + } + + /** + *

Appends to the builder the deep comparison of + * two double arrays.

+ * + *
    + *
  1. Check if arrays are the same using ==
  2. + *
  3. Check if for null, null is less than non-null
  4. + *
  5. Check array length, a shorter length array is less than a longer length array
  6. + *
  7. Check array contents element by element using {@link #append(double, double)}
  8. + *
+ * + * @param lhs left-hand array + * @param rhs right-hand array + * @return this - used to chain append calls + */ + public CompareToBuilder append(final double[] lhs, final double[] rhs) { + if (comparison != 0) { + return this; + } + if (lhs == rhs) { + return this; + } + if (lhs == null) { + comparison = -1; + return this; + } + if (rhs == null) { + comparison = +1; + return this; + } + if (lhs.length != rhs.length) { + comparison = (lhs.length < rhs.length) ? -1 : +1; + return this; + } + for (int i = 0; i < lhs.length && comparison == 0; i++) { + append(lhs[i], rhs[i]); + } + return this; + } + + /** + *

Appends to the builder the deep comparison of + * two float arrays.

+ * + *
    + *
  1. Check if arrays are the same using ==
  2. + *
  3. Check if for null, null is less than non-null
  4. + *
  5. Check array length, a shorter length array is less than a longer length array
  6. + *
  7. Check array contents element by element using {@link #append(float, float)}
  8. + *
+ * + * @param lhs left-hand array + * @param rhs right-hand array + * @return this - used to chain append calls + */ + public CompareToBuilder append(final float[] lhs, final float[] rhs) { + if (comparison != 0) { + return this; + } + if (lhs == rhs) { + return this; + } + if (lhs == null) { + comparison = -1; + return this; + } + if (rhs == null) { + comparison = +1; + return this; + } + if (lhs.length != rhs.length) { + comparison = (lhs.length < rhs.length) ? -1 : +1; + return this; + } + for (int i = 0; i < lhs.length && comparison == 0; i++) { + append(lhs[i], rhs[i]); + } + return this; + } + + /** + *

Appends to the builder the deep comparison of + * two boolean arrays.

+ * + *
    + *
  1. Check if arrays are the same using ==
  2. + *
  3. Check if for null, null is less than non-null
  4. + *
  5. Check array length, a shorter length array is less than a longer length array
  6. + *
  7. Check array contents element by element using {@link #append(boolean, boolean)}
  8. + *
+ * + * @param lhs left-hand array + * @param rhs right-hand array + * @return this - used to chain append calls + */ + public CompareToBuilder append(final boolean[] lhs, final boolean[] rhs) { + if (comparison != 0) { + return this; + } + if (lhs == rhs) { + return this; + } + if (lhs == null) { + comparison = -1; + return this; + } + if (rhs == null) { + comparison = +1; + return this; + } + if (lhs.length != rhs.length) { + comparison = (lhs.length < rhs.length) ? -1 : +1; + return this; + } + for (int i = 0; i < lhs.length && comparison == 0; i++) { + append(lhs[i], rhs[i]); + } + return this; + } + + //----------------------------------------------------------------------- + /** + * Returns a negative integer, a positive integer, or zero as + * the builder has judged the "left-hand" side + * as less than, greater than, or equal to the "right-hand" + * side. + * + * @return final comparison result + * @see #build() + */ + public int toComparison() { + return comparison; + } + + /** + * Returns a negative Integer, a positive Integer, or zero as + * the builder has judged the "left-hand" side + * as less than, greater than, or equal to the "right-hand" + * side. + * + * @return final comparison result as an Integer + * @see #toComparison() + * @since 3.0 + */ + @Override + public Integer build() { + return Integer.valueOf(toComparison()); + } + + static String[] toNoNullStringArray(final Collection collection) { + if (collection == null) { + return ArrayUtils.EMPTY_STRING_ARRAY; + } + return toNoNullStringArray(collection.toArray()); + } + + static String[] toNoNullStringArray(final Object[] array) { + final List list = new ArrayList(array.length); + for (final Object e : array) { + if (e != null) { + list.add(e.toString()); + } + } + return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY); + } + +} diff --git a/mongo-plus-parent/pom.xml b/mongo-plus-parent/pom.xml index b94818bb70a911fcfd9baa8f786c029e35127c60..02ace85f060b7ce288951bc0db1b542c4c92f374 100644 --- a/mongo-plus-parent/pom.xml +++ b/mongo-plus-parent/pom.xml @@ -17,7 +17,7 @@ ../mongo-plus-annotation ../mongo-plus-core ../mongo-plus-boot-starter - ../mongo-plus-solon-plugin + @@ -143,7 +143,7 @@ - + diff --git a/mongo-plus-solon-plugin/pom.xml b/mongo-plus-solon-plugin/pom.xml index 2f950005b6e471c1755969b4ff58a950b369c7fb..1dcfdddc2a11b87d029dd13fe3b0216649f1385c 100644 --- a/mongo-plus-solon-plugin/pom.xml +++ b/mongo-plus-solon-plugin/pom.xml @@ -118,7 +118,7 @@ - + diff --git a/mongo-plus-solon-plugin/src/main/java/com/anwen/mongo/config/MongoPlusAutoConfiguration.java b/mongo-plus-solon-plugin/src/main/java/com/anwen/mongo/config/MongoPlusAutoConfiguration.java index e0983b82c3cc7d5e841756daa805a38d8edcdc65..418f653661073805be09e3cad775f5b844fcbc3e 100644 --- a/mongo-plus-solon-plugin/src/main/java/com/anwen/mongo/config/MongoPlusAutoConfiguration.java +++ b/mongo-plus-solon-plugin/src/main/java/com/anwen/mongo/config/MongoPlusAutoConfiguration.java @@ -2,17 +2,17 @@ package com.anwen.mongo.config; import com.anwen.mongo.annotation.collection.CollectionName; import com.anwen.mongo.cache.global.HandlerCache; -import com.anwen.mongo.cache.global.InterceptorCache; +import com.anwen.mongo.cache.global.ListenerCache; import com.anwen.mongo.conn.CollectionManager; import com.anwen.mongo.conn.ConnectMongoDB; import com.anwen.mongo.convert.CollectionNameConvert; -import com.anwen.mongo.execute.ExecutorFactory; import com.anwen.mongo.handlers.DocumentHandler; import com.anwen.mongo.handlers.MetaObjectHandler; -import com.anwen.mongo.interceptor.Interceptor; -import com.anwen.mongo.interceptor.business.BlockAttackInnerInterceptor; -import com.anwen.mongo.interceptor.business.LogInterceptor; +import com.anwen.mongo.listener.Listener; +import com.anwen.mongo.listener.business.BlockAttackInnerListener; +import com.anwen.mongo.listener.business.LogListener; import com.anwen.mongo.manager.MongoPlusClient; +import com.anwen.mongo.mapper.BaseMapper; import com.anwen.mongo.property.MongoDBCollectionProperty; import com.anwen.mongo.property.MongoDBLogProperty; import com.anwen.mongo.service.IService; @@ -41,7 +41,7 @@ import java.util.stream.Collectors; **/ public class MongoPlusAutoConfiguration { - private final ExecutorFactory factory; + private final BaseMapper baseMapper; private final MongoPlusClient mongoPlusClient; @@ -53,13 +53,13 @@ public class MongoPlusAutoConfiguration { Logger logger = LoggerFactory.getLogger(MongoPlusAutoConfiguration.class); - public MongoPlusAutoConfiguration(ExecutorFactory factory, MongoPlusClient mongoPlusClient, @Inject CollectionNameConvert collectionNameConvert, MongoDBLogProperty mongoDBLogProperty, MongoDBCollectionProperty mongoDBCollectionProperty){ + public MongoPlusAutoConfiguration(BaseMapper baseMapper, MongoPlusClient mongoPlusClient, @Inject CollectionNameConvert collectionNameConvert, MongoDBLogProperty mongoDBLogProperty, MongoDBCollectionProperty mongoDBCollectionProperty){ mongoDBCollectionProperty = Optional.ofNullable(mongoDBCollectionProperty).orElseGet(MongoDBCollectionProperty::new); - this.factory = factory; this.collectionNameConvert = collectionNameConvert; this.mongoPlusClient = mongoPlusClient; this.mongoDBLogProperty = mongoDBLogProperty; this.mongoDBCollectionProperty = mongoDBCollectionProperty; + this.baseMapper = baseMapper; AppContext context = Solon.context(); context.subBeansOfType(IService.class, bean -> { if (bean instanceof ServiceImpl){ @@ -85,9 +85,8 @@ public class MongoPlusAutoConfiguration { serviceImpl.setClazz(clazz); String database = initFactory(clazz); //这里需要将MongoPlusClient给工厂 - factory.setMongoPlusClient(mongoPlusClient); serviceImpl.setDatabase(database); - serviceImpl.setFactory(factory); + serviceImpl.setBaseMapper(baseMapper); } public String initFactory(Class clazz) { @@ -167,18 +166,18 @@ public class MongoPlusAutoConfiguration { * @date 2023/11/22 18:39 */ private void setInterceptor(AppContext context){ - List interceptors = new ArrayList<>(); + List listeners = new ArrayList<>(); if (mongoDBLogProperty.getLog()){ - interceptors.add(new LogInterceptor()); + listeners.add(new LogListener()); } if (mongoDBCollectionProperty.getBlockAttackInner()){ - interceptors.add(new BlockAttackInnerInterceptor()); + listeners.add(new BlockAttackInnerListener()); } - List interceptorCollection = context.getBeansOfType(Interceptor.class); - if (CollUtil.isNotEmpty(interceptorCollection)){ - interceptors.addAll(interceptorCollection); + List listenerCollection = context.getBeansOfType(Listener.class); + if (CollUtil.isNotEmpty(listenerCollection)){ + listeners.addAll(listenerCollection); } - InterceptorCache.interceptors = interceptors.stream().sorted(Comparator.comparingInt(Interceptor::getOrder)).collect(Collectors.toList()); + ListenerCache.listeners = listeners.stream().sorted(Comparator.comparingInt(Listener::getOrder)).collect(Collectors.toList()); } } diff --git a/mongo-plus-solon-plugin/src/main/java/com/anwen/mongo/config/MongoPlusConfiguration.java b/mongo-plus-solon-plugin/src/main/java/com/anwen/mongo/config/MongoPlusConfiguration.java index 470c02d4ef023db708c92849fadbf6e8ce5a53a5..22409061c57d84a9cb0c811df94d7c1ca37332be 100644 --- a/mongo-plus-solon-plugin/src/main/java/com/anwen/mongo/config/MongoPlusConfiguration.java +++ b/mongo-plus-solon-plugin/src/main/java/com/anwen/mongo/config/MongoPlusConfiguration.java @@ -2,9 +2,9 @@ package com.anwen.mongo.config; import com.anwen.mongo.cache.global.MongoPlusClientCache; import com.anwen.mongo.convert.CollectionNameConvert; -import com.anwen.mongo.execute.ExecutorFactory; -import com.anwen.mongo.interceptor.BaseInterceptor; +import com.anwen.mongo.listener.BaseListener; import com.anwen.mongo.manager.MongoPlusClient; +import com.anwen.mongo.mapper.BaseMapper; import com.anwen.mongo.mapper.MongoPlusMapMapper; import com.anwen.mongo.property.MongoDBCollectionProperty; import com.anwen.mongo.property.MongoDBConnectProperty; @@ -47,7 +47,7 @@ public class MongoPlusConfiguration { @Condition(onMissingBean = MongoClient.class) public MongoClient mongoClient(){ return MongoClients.create(MongoClientSettings.builder() - .applyConnectionString(new ConnectionString(new UrlJoint(mongoDBConnectProperty).jointMongoUrl())).commandListenerList(Collections.singletonList(new BaseInterceptor())).build()); + .applyConnectionString(new ConnectionString(new UrlJoint(mongoDBConnectProperty).jointMongoUrl())).commandListenerList(Collections.singletonList(new BaseListener())).build()); } @Bean @@ -67,19 +67,10 @@ public class MongoPlusConfiguration { return MongoCollectionUtils.build(mongoDBCollectionProperty.getMappingStrategy()); } - @Bean - @Condition(onMissingBean = ExecutorFactory.class) - public ExecutorFactory executeFactory(CollectionNameConvert collectionNameConvert){ - return ExecutorFactory.builder() - .baseProperty(mongoDBConnectProperty) - .collectionNameConvert(collectionNameConvert) - .build(); - } - @Bean @Condition(onMissingBean = MongoPlusMapMapper.class) - public MongoPlusMapMapper mongoPlusMapMapper(ExecutorFactory factory) { - return new MongoPlusMapMapper(factory); + public MongoPlusMapMapper mongoPlusMapMapper(MongoPlusClient mongoPlusClient) { + return new MongoPlusMapMapper(mongoPlusClient); } @Bean("mongoTransactionalAspect") @@ -90,11 +81,11 @@ public class MongoPlusConfiguration { } @Bean - public MongoPlusAutoConfiguration mongoPlusAutoConfiguration(@Inject ExecutorFactory factory, + public MongoPlusAutoConfiguration mongoPlusAutoConfiguration(@Inject BaseMapper baseMapper, @Inject MongoPlusClient mongoPlusClient, @Inject CollectionNameConvert collectionNameConvert, @Inject("${mongo-plus}") MongoDBLogProperty mongoDBLogProperty){ - return new MongoPlusAutoConfiguration(factory,mongoPlusClient,collectionNameConvert,mongoDBLogProperty,mongoDBCollectionProperty); + return new MongoPlusAutoConfiguration(baseMapper,mongoPlusClient,collectionNameConvert,mongoDBLogProperty,mongoDBCollectionProperty); } } diff --git a/mongo-plus-solon-plugin/src/main/java/com/anwen/mongo/config/XPluginAuto.java b/mongo-plus-solon-plugin/src/main/java/com/anwen/mongo/config/XPluginAuto.java index d2b9e0d6c52a0d4ea2c15b36857354ea3d2deed9..bfbe8748e77b9177020b5a180620a306bef7d7c4 100644 --- a/mongo-plus-solon-plugin/src/main/java/com/anwen/mongo/config/XPluginAuto.java +++ b/mongo-plus-solon-plugin/src/main/java/com/anwen/mongo/config/XPluginAuto.java @@ -1,7 +1,6 @@ package com.anwen.mongo.config; import com.anwen.mongo.annotation.transactional.MongoTransactional; -import com.anwen.mongo.cache.global.MongoPlusClientCache; import com.anwen.mongo.property.MongoDBFieldProperty; import com.anwen.mongo.transactional.MongoTransactionalAspect; import com.mongodb.client.MongoClient;