From 180560456ba39ba669b723da4aba575cf198bd69 Mon Sep 17 00:00:00 2001 From: wulang Date: Wed, 16 Nov 2022 20:23:15 +0800 Subject: [PATCH] feat:add db lock --- .../conf/hippo4j_manager.sql | 5 ++ .../server/config/DataBaseConfiguration.java | 15 ++++ .../cn/hippo4j/config/mapper/LockMapper.java | 31 +++++++ .../cn/hippo4j/config/model/LockInfo.java | 28 +++++++ .../config/service/biz/LockService.java | 34 ++++++++ .../service/biz/impl/DbLockServiceImpl.java | 84 +++++++++++++++++++ 6 files changed, 197 insertions(+) create mode 100644 hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/mapper/LockMapper.java create mode 100644 hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/model/LockInfo.java create mode 100644 hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/LockService.java create mode 100644 hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/impl/DbLockServiceImpl.java diff --git a/hippo4j-server/hippo4j-bootstrap/conf/hippo4j_manager.sql b/hippo4j-server/hippo4j-bootstrap/conf/hippo4j_manager.sql index 81c33a77..00e0b1df 100644 --- a/hippo4j-server/hippo4j-bootstrap/conf/hippo4j_manager.sql +++ b/hippo4j-server/hippo4j-bootstrap/conf/hippo4j_manager.sql @@ -230,6 +230,11 @@ CREATE TABLE `his_config_verify` ( PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET=utf8mb4 COMMENT = '参数变更审核记录表'; +DROP TABLE IF EXISTS `hippo4j_lock`; +CREATE TABLE `hippo4j_lock` ( + `lock_name` varchar(50) NOT NULL COMMENT '锁名称', + PRIMARY KEY (`lock_name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /* Init SQL */ INSERT IGNORE INTO `tenant` (`id`, `tenant_id`, `tenant_name`, `tenant_desc`, `owner`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES ('1', 'prescription', '处方组', '负责维护处方服务, 包括不限于电子处方等业务', '谢良辰', '2021-10-24 13:42:11', '2021-10-24 13:42:11', '0'); diff --git a/hippo4j-server/hippo4j-bootstrap/src/main/java/cn/hippo4j/server/config/DataBaseConfiguration.java b/hippo4j-server/hippo4j-bootstrap/src/main/java/cn/hippo4j/server/config/DataBaseConfiguration.java index 607d4370..d075cf64 100644 --- a/hippo4j-server/hippo4j-bootstrap/src/main/java/cn/hippo4j/server/config/DataBaseConfiguration.java +++ b/hippo4j-server/hippo4j-bootstrap/src/main/java/cn/hippo4j/server/config/DataBaseConfiguration.java @@ -21,6 +21,10 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.transaction.support.TransactionTemplate; + +import javax.sql.DataSource; /** * Database configuration. @@ -41,4 +45,15 @@ public class DataBaseConfiguration { dataSourceProperties.setInitEnable(initEnable); return dataSourceProperties; } + + @Bean + @ConditionalOnMissingBean(value = TransactionTemplate.class) + public TransactionTemplate transactionTemplate(DataSource dataSource) { + DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); + dataSourceTransactionManager.setDataSource(dataSource); + TransactionTemplate transactionTemplate = new TransactionTemplate(); + transactionTemplate.setTransactionManager(dataSourceTransactionManager); + transactionTemplate.setPropagationBehaviorName("PROPAGATION_REQUIRED"); + return transactionTemplate; + } } diff --git a/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/mapper/LockMapper.java b/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/mapper/LockMapper.java new file mode 100644 index 00000000..047e53e4 --- /dev/null +++ b/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/mapper/LockMapper.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.config.mapper; + +import cn.hippo4j.config.model.LockInfo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +@Mapper +public interface LockMapper extends BaseMapper { + + @Select("select * from hippo4j_lock where lock_name = #{lockName} for update") + String tryLock(@Param("lockName") String lockName); +} diff --git a/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/model/LockInfo.java b/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/model/LockInfo.java new file mode 100644 index 00000000..baf96bb8 --- /dev/null +++ b/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/model/LockInfo.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.config.model; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("hippo4j_lock") +public class LockInfo { + + private String lockName; +} diff --git a/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/LockService.java b/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/LockService.java new file mode 100644 index 00000000..678d9f2a --- /dev/null +++ b/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/LockService.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.config.service.biz; + +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * Lock Service + */ +public interface LockService { + + void tryLocK(String lockName, T t, Consumer consumer); + + R tryLocK(String lockName, T t, Function function); + + R tryLocK(String lockName, T t, Function function, Supplier errorResult); +} diff --git a/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/impl/DbLockServiceImpl.java b/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/impl/DbLockServiceImpl.java new file mode 100644 index 00000000..01f0bd7a --- /dev/null +++ b/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/service/biz/impl/DbLockServiceImpl.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.config.service.biz.impl; + +import cn.hippo4j.config.mapper.LockMapper; +import cn.hippo4j.config.service.biz.LockService; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionTemplate; + +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * db lock + */ +@Service +@AllArgsConstructor +public class DbLockServiceImpl implements LockService { + + private TransactionTemplate transactionTemplate; + + private final LockMapper lockMapper; + + @Override + public void tryLocK(String lockName, T t, Consumer consumer) { + transactionTemplate.execute(status -> { + try { + lockMapper.tryLock(lockName); + consumer.accept(t); + } catch (Exception e) { + status.setRollbackOnly(); + throw new RuntimeException(e); + } + return null; + }); + } + + @Override + public R tryLocK(String lockName, T t, Function function) { + return transactionTemplate.execute(status -> { + R r = null; + try { + lockMapper.tryLock(lockName); + r = function.apply(t); + } catch (Exception e) { + status.setRollbackOnly(); + throw new RuntimeException(e); + } + return r; + }); + } + + @Override + public R tryLocK(String lockName, T t, Function function, Supplier errorResult) { + return transactionTemplate.execute(status -> { + R r; + try { + lockMapper.tryLock(lockName); + r = function.apply(t); + } catch (Exception e) { + status.setRollbackOnly(); + return errorResult.get(); + } + return r; + }); + } +}