From 00f6fc97beacfcfc7d4d52ba793e411f8134ba1f Mon Sep 17 00:00:00 2001 From: "trifolium.wang" Date: Wed, 3 Apr 2024 11:39:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E5=AF=B9solon?= =?UTF-8?q?=E7=9A=84=E6=8F=92=E4=BB=B6=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 1 + solon-plugin/pom.xml | 87 ++++++++++++++ .../mybatis/solon/TkMapperAdapterFactory.java | 24 ++++ .../mybatis/solon/TkMapperMybatisAdapter.java | 112 ++++++++++++++++++ .../java/tk/mybatis/solon/XPluginImpl.java | 22 ++++ .../mybatis-tkmapper-solon-plugin.properties | 2 + .../tk/mybatis/solon/test/TkMapperTest.java | 15 +++ .../mybatis/solon/test/conf/TestConfig.java | 48 ++++++++ .../tk/mybatis/solon/test/entity/User.java | 108 +++++++++++++++++ .../mybatis/solon/test/mapper/UserMapper.java | 18 +++ .../test/service/TkMapperServiceTest.java | 85 +++++++++++++ solon-plugin/src/test/resources/app.yml | 21 ++++ .../src/test/resources/mapper/UserMapper.xml | 26 ++++ 13 files changed, 569 insertions(+) create mode 100644 solon-plugin/pom.xml create mode 100644 solon-plugin/src/main/java/tk/mybatis/solon/TkMapperAdapterFactory.java create mode 100644 solon-plugin/src/main/java/tk/mybatis/solon/TkMapperMybatisAdapter.java create mode 100644 solon-plugin/src/main/java/tk/mybatis/solon/XPluginImpl.java create mode 100644 solon-plugin/src/main/resources/META-INF/solon/mybatis-tkmapper-solon-plugin.properties create mode 100644 solon-plugin/src/test/java/tk/mybatis/solon/test/TkMapperTest.java create mode 100644 solon-plugin/src/test/java/tk/mybatis/solon/test/conf/TestConfig.java create mode 100644 solon-plugin/src/test/java/tk/mybatis/solon/test/entity/User.java create mode 100644 solon-plugin/src/test/java/tk/mybatis/solon/test/mapper/UserMapper.java create mode 100644 solon-plugin/src/test/java/tk/mybatis/solon/test/service/TkMapperServiceTest.java create mode 100644 solon-plugin/src/test/resources/app.yml create mode 100644 solon-plugin/src/test/resources/mapper/UserMapper.xml diff --git a/pom.xml b/pom.xml index 2f2fc2b34..974cb0737 100644 --- a/pom.xml +++ b/pom.xml @@ -141,6 +141,7 @@ weekend generator spring-boot-starter + solon-plugin diff --git a/solon-plugin/pom.xml b/solon-plugin/pom.xml new file mode 100644 index 000000000..832f263a8 --- /dev/null +++ b/solon-plugin/pom.xml @@ -0,0 +1,87 @@ + + + + + 4.0.0 + + tk.mybatis + mapper-modules + ${revision} + + mapper-solon-plugin + jar + + mapper-solon-plugin + Solon Support for Mapper + https://github.com/abel533/solon-plugin/ + + + 2.7.3 + + + + + + org.noear + mybatis-solon-plugin + ${solon.version} + + + + tk.mybatis + mapper-core + ${project.version} + + + + tk.mybatis + mapper-base + ${project.version} + + + + org.noear + solon-test-junit4 + ${solon.version} + test + + + + com.h2database + h2 + 1.4.200 + test + + + + com.zaxxer + HikariCP + 4.0.3 + test + + + + diff --git a/solon-plugin/src/main/java/tk/mybatis/solon/TkMapperAdapterFactory.java b/solon-plugin/src/main/java/tk/mybatis/solon/TkMapperAdapterFactory.java new file mode 100644 index 000000000..e36cd0bf3 --- /dev/null +++ b/solon-plugin/src/main/java/tk/mybatis/solon/TkMapperAdapterFactory.java @@ -0,0 +1,24 @@ +package tk.mybatis.solon; + +import org.apache.ibatis.solon.MybatisAdapter; +import org.apache.ibatis.solon.MybatisAdapterFactory; +import org.noear.solon.core.BeanWrap; +import org.noear.solon.core.Props; + +/** + * @title: tkMybatis Adapter Factory + * @author: trifolium.wang + * @date: 2024/4/1 + * @since 2.7.3 + */ +public class TkMapperAdapterFactory implements MybatisAdapterFactory { + @Override + public MybatisAdapter create(BeanWrap dsWrap) { + return new TkMapperMybatisAdapter(dsWrap); + } + + @Override + public MybatisAdapter create(BeanWrap dsWrap, Props dsProps) { + return new TkMapperMybatisAdapter(dsWrap, dsProps); + } +} diff --git a/solon-plugin/src/main/java/tk/mybatis/solon/TkMapperMybatisAdapter.java b/solon-plugin/src/main/java/tk/mybatis/solon/TkMapperMybatisAdapter.java new file mode 100644 index 000000000..fb92d69ff --- /dev/null +++ b/solon-plugin/src/main/java/tk/mybatis/solon/TkMapperMybatisAdapter.java @@ -0,0 +1,112 @@ +package tk.mybatis.solon; + +import org.apache.ibatis.mapping.Environment; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.solon.integration.MybatisAdapterDefault; +import org.noear.solon.core.BeanWrap; +import org.noear.solon.core.Props; +import org.noear.solon.core.PropsConverter; +import org.noear.solon.core.VarHolder; +import tk.mybatis.mapper.entity.Config; +import tk.mybatis.mapper.mapperhelper.MapperHelper; + +/** + * @title: TkMybatis Adapter + * @author: trifolium.wang + * @date: 2024/4/1 + * @since 2.7.3 + */ +public class TkMapperMybatisAdapter extends MybatisAdapterDefault { + + protected Config tkConfig; + + protected MapperHelper mapperHelper; + + protected TkMapperMybatisAdapter(BeanWrap dsWrap) { + super(dsWrap); + + dsWrap.context().getBeanAsync(Config.class, bean -> { + tkConfig = bean; + }); + + dsWrap.context().getBeanAsync(MapperHelper.class, bean -> { + mapperHelper = bean; + }); + } + + protected TkMapperMybatisAdapter(BeanWrap dsWrap, Props dsProps) { + super(dsWrap, dsProps); + + dsWrap.context().getBeanAsync(Config.class, bean -> { + tkConfig = bean; + }); + + dsWrap.context().getBeanAsync(MapperHelper.class, bean -> { + mapperHelper = bean; + }); + } + + @Override + protected void initConfiguration(Environment environment) { + config = new tk.mybatis.mapper.session.Configuration(); + config.setEnvironment(environment); + + Props mybatisProps = dsProps.getProp("configuration"); + if (!mybatisProps.isEmpty()) { + PropsConverter.global().convert(mybatisProps, config, Configuration.class, null); + } + } + + @Override + public SqlSessionFactory getFactory() { + if (factory == null) { + builderMapperHelper(); + factory = factoryBuilder.build(config); + } + return factory; + } + + @Override + public void injectTo(VarHolder varH) { + super.injectTo(varH); + + //@Db("db1") Config tkConfig; + if (Config.class.isAssignableFrom(varH.getType())) { + varH.setValue(this.tkConfig); + } + + //@Db("db1") tk.mybatis.mapper.session.Configuration configuration; + if (tk.mybatis.mapper.session.Configuration.class.isAssignableFrom(varH.getType())) { + varH.setValue(getConfiguration()); + } + + //@Db("db1") MapperHelper mapperHelper; + if (MapperHelper.class.isAssignableFrom(varH.getType())) { + varH.setValue(this.mapperHelper); + } + } + + /** + * 通过使用 tk.mybatis.mapper.session.Configuration + * 替换 MyBatis 中的 org.apache.ibatis.session.Configuration. + * 重写原 Configuration 中的 addMappedStatement实现 + */ + private void builderMapperHelper() { + Props cfgProps = dsProps.getProp("tk.mapper"); + + if (tkConfig == null) { + tkConfig = new Config(); + } + + if (!cfgProps.isEmpty()) { + PropsConverter.global().convert(cfgProps, tkConfig, Config.class, null); + } + if (mapperHelper == null) { + mapperHelper = new MapperHelper(); + } + + mapperHelper.setConfig(tkConfig); + ((tk.mybatis.mapper.session.Configuration) config).setMapperHelper(mapperHelper); + } +} diff --git a/solon-plugin/src/main/java/tk/mybatis/solon/XPluginImpl.java b/solon-plugin/src/main/java/tk/mybatis/solon/XPluginImpl.java new file mode 100644 index 000000000..75ef5c2f7 --- /dev/null +++ b/solon-plugin/src/main/java/tk/mybatis/solon/XPluginImpl.java @@ -0,0 +1,22 @@ +package tk.mybatis.solon; + +import org.apache.ibatis.solon.integration.MybatisAdapterManager; +import org.noear.solon.core.AppContext; +import org.noear.solon.core.Plugin; + +/** + * @title: TkMybatis的Solon插件 + * @author: trifolium.wang + * @date: 2024/4/1 + * @since 2.7.3 + */ +public class XPluginImpl implements Plugin { + + + @Override + public void start(AppContext context) throws Throwable { + + MybatisAdapterManager.setAdapterFactory(new TkMapperAdapterFactory()); + } + +} diff --git a/solon-plugin/src/main/resources/META-INF/solon/mybatis-tkmapper-solon-plugin.properties b/solon-plugin/src/main/resources/META-INF/solon/mybatis-tkmapper-solon-plugin.properties new file mode 100644 index 000000000..14e843dbd --- /dev/null +++ b/solon-plugin/src/main/resources/META-INF/solon/mybatis-tkmapper-solon-plugin.properties @@ -0,0 +1,2 @@ +solon.plugin=tk.mybatis.solon.XPluginImpl +solon.plugin.priority=3 \ No newline at end of file diff --git a/solon-plugin/src/test/java/tk/mybatis/solon/test/TkMapperTest.java b/solon-plugin/src/test/java/tk/mybatis/solon/test/TkMapperTest.java new file mode 100644 index 000000000..f73d3962b --- /dev/null +++ b/solon-plugin/src/test/java/tk/mybatis/solon/test/TkMapperTest.java @@ -0,0 +1,15 @@ +package tk.mybatis.solon.test; + +import org.noear.solon.Solon; + +/** + * @title: TkMapperTest + * @author: trifolium.wang + * @date: 2024/4/2 + */ +public class TkMapperTest { + + public static void main(String[] args) { + Solon.start(TkMapperTest.class, args); + } +} diff --git a/solon-plugin/src/test/java/tk/mybatis/solon/test/conf/TestConfig.java b/solon-plugin/src/test/java/tk/mybatis/solon/test/conf/TestConfig.java new file mode 100644 index 000000000..5fa149a1c --- /dev/null +++ b/solon-plugin/src/test/java/tk/mybatis/solon/test/conf/TestConfig.java @@ -0,0 +1,48 @@ +package tk.mybatis.solon.test.conf; + +import com.zaxxer.hikari.HikariDataSource; +import org.noear.solon.annotation.Bean; +import org.noear.solon.annotation.Configuration; +import org.noear.solon.annotation.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.Statement; + +/** + * @title: TestConfig + * @author: trifolium.wang + * @date: 2024/4/2 + */ +@Configuration +public class TestConfig { + + Logger log = LoggerFactory.getLogger(TestConfig.class); + + @Bean(name = "db1", typed = true) + public DataSource db1(@Inject("${test.db1}") HikariDataSource ds) { + try { + Connection conn = ds.getConnection(); + Statement statement = conn.createStatement(); + statement.execute("CREATE TABLE user (" + + " `id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY," + + " `name` varchar(255) DEFAULT NULL," + + " `age` int DEFAULT NULL," + + " `create_time` datetime DEFAULT NULL," + + " `is_del` tinyint(1) DEFAULT NULL" + + ")"); + + statement.execute("INSERT INTO `user` (`id`, `name`, `age`, `create_time`, `is_del`) VALUES (1, '张三', 11, '2024-04-02 13:38:56', 0);\n" + + "INSERT INTO `user` (`id`, `name`, `age`, `create_time`, `is_del`) VALUES (2, '李四', 3, '2024-04-02 13:39:08', 0);\n" + + "INSERT INTO `user` (`id`, `name`, `age`, `create_time`, `is_del`) VALUES (3, '张麻子', 43, '2024-04-02 13:39:20', 0);"); + statement.close(); + conn.close(); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new RuntimeException("Datasource initialization Failure!"); + } + return ds; + } +} diff --git a/solon-plugin/src/test/java/tk/mybatis/solon/test/entity/User.java b/solon-plugin/src/test/java/tk/mybatis/solon/test/entity/User.java new file mode 100644 index 000000000..900149620 --- /dev/null +++ b/solon-plugin/src/test/java/tk/mybatis/solon/test/entity/User.java @@ -0,0 +1,108 @@ +package tk.mybatis.solon.test.entity; + +import org.noear.snack.core.utils.DateUtil; +import tk.mybatis.mapper.annotation.LogicDelete; + +import javax.persistence.Column; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.Date; + +@Table(name = "`user`") +public class User { + @Id + @Column(name = "id") + @GeneratedValue(generator = "JDBC") + private Long id; + + @Column(name = "`name`") + private String name; + + @Column(name = "age") + private Integer age; + + @Column(name = "create_time") + private Date createTime; + + @LogicDelete + @Column(name = "is_del") + private Boolean isDel; + + /** + * @return id + */ + public Long getId() { + return id; + } + + /** + * @param id + */ + public void setId(Long id) { + this.id = id; + } + + /** + * @return name + */ + public String getName() { + return name; + } + + /** + * @param name + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return age + */ + public Integer getAge() { + return age; + } + + /** + * @param age + */ + public void setAge(Integer age) { + this.age = age; + } + + /** + * @return create_time + */ + public Date getCreateTime() { + return createTime; + } + + /** + * @param createTime + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + /** + * @return is_del + */ + public Boolean getIsDel() { + return isDel; + } + + /** + * @param isDel + */ + public void setIsDel(Boolean isDel) { + this.isDel = isDel; + } + + @Override + public String toString() { + + return String.format("id:%d, name:%s, age:%d, createTime:%s", id, name, age, + createTime != null ? DateUtil.format(createTime, DateUtil.FORMAT_19_b) : null); + } +} \ No newline at end of file diff --git a/solon-plugin/src/test/java/tk/mybatis/solon/test/mapper/UserMapper.java b/solon-plugin/src/test/java/tk/mybatis/solon/test/mapper/UserMapper.java new file mode 100644 index 000000000..0dc60d2e6 --- /dev/null +++ b/solon-plugin/src/test/java/tk/mybatis/solon/test/mapper/UserMapper.java @@ -0,0 +1,18 @@ +package tk.mybatis.solon.test.mapper; + +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.ResultMap; +import org.apache.ibatis.annotations.Select; +import tk.mybatis.mapper.common.Mapper; +import tk.mybatis.solon.test.entity.User; + +import java.util.List; + +public interface UserMapper extends Mapper { + + @ResultMap("tk.mybatis.solon.test.mapper.UserMapper.BaseResultMap") + @Select("SELECT * FROM user WHERE is_del = 0 AND age > #{age}") + List findByGTAge(@Param("age") Integer age); + + List findByName(@Param("name") String name); +} \ No newline at end of file diff --git a/solon-plugin/src/test/java/tk/mybatis/solon/test/service/TkMapperServiceTest.java b/solon-plugin/src/test/java/tk/mybatis/solon/test/service/TkMapperServiceTest.java new file mode 100644 index 000000000..a0e2a85ff --- /dev/null +++ b/solon-plugin/src/test/java/tk/mybatis/solon/test/service/TkMapperServiceTest.java @@ -0,0 +1,85 @@ +package tk.mybatis.solon.test.service; + +import org.apache.ibatis.solon.annotation.Db; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.noear.solon.test.SolonJUnit4ClassRunner; +import org.noear.solon.test.SolonTest; +import org.noear.solon.test.annotation.Rollback; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import tk.mybatis.mapper.entity.Example; +import tk.mybatis.solon.test.TkMapperTest; +import tk.mybatis.solon.test.entity.User; +import tk.mybatis.solon.test.mapper.UserMapper; + +import java.util.List; + +/** + * @title: TkMapperServiceTest + * @author: trifolium.wang + * @date: 2024/4/2 + */ +//@Ignore +@SolonTest(TkMapperTest.class) +@RunWith(SolonJUnit4ClassRunner.class) +public class TkMapperServiceTest { + + Logger log = LoggerFactory.getLogger(TkMapperServiceTest.class); + + @Db("db1") + private UserMapper userMapper; + + @Test + public void all() { + + userMapper.selectAll().forEach(u -> log.info(u.toString())); + } + + /** + * 根据主键查询 + */ + @Test + public void byId() { + + User user = userMapper.selectByPrimaryKey(1); + log.info(user == null ? null : user.toString()); + } + + /** + * 根据example查询 + */ + @Test + public void exampleQuery() { + Example example = new Example(User.class); + example.and().andLike("name", "%张%"); + userMapper.selectByExample(example).forEach(u -> log.info(u.toString())); + } + + /** + * mybatis 原生查询 + */ + @Test + public void rawMybatisQuery() { + + userMapper.findByGTAge(11).forEach(u -> log.info(u.toString())); + } + + /** + * mybatis 逻辑删除和添加,并测试事务 + */ + @Test + @Rollback + public void logicDelInsert() { + + List users = userMapper.findByName("张麻子"); + if (!users.isEmpty()) { + User user = users.get(0); + userMapper.deleteByPrimaryKey(user.getId()); + user.setId(null); + userMapper.insert(user); + } + } + +} diff --git a/solon-plugin/src/test/resources/app.yml b/solon-plugin/src/test/resources/app.yml new file mode 100644 index 000000000..a76e959f5 --- /dev/null +++ b/solon-plugin/src/test/resources/app.yml @@ -0,0 +1,21 @@ +# 配置数据源 +test: + db1: + jdbcUrl: jdbc:h2:mem:h2DB + driverClassName: org.h2.Driver + username: root + password: root + +mybatis: + db1: + typeAliases: + - "tk.mybatis.solon.test.entity.*" + mappers: + - "classpath:mapper/*.xml" + +# tk mapper的配置 + tk: + mapper: + style: camelhumpandlowercase + safe-update: true + safe-delete: true diff --git a/solon-plugin/src/test/resources/mapper/UserMapper.xml b/solon-plugin/src/test/resources/mapper/UserMapper.xml new file mode 100644 index 000000000..3a279814c --- /dev/null +++ b/solon-plugin/src/test/resources/mapper/UserMapper.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + id, `name`, age, create_time, is_del + + + + \ No newline at end of file