diff --git a/mallinkAdmin/pom.xml b/mallinkAdmin/pom.xml index 02831b8d3..ec65f306d 100644 --- a/mallinkAdmin/pom.xml +++ b/mallinkAdmin/pom.xml @@ -18,7 +18,11 @@ mallinkService 1.0 - + + com.iformall + mybatis-multi-tenancy + 1.0 + diff --git a/mallinkBApi/pom.xml b/mallinkBApi/pom.xml index 9f2f013a8..a6c7c0588 100644 --- a/mallinkBApi/pom.xml +++ b/mallinkBApi/pom.xml @@ -17,7 +17,11 @@ mallinkService 1.0 - + + com.iformall + mybatis-multi-tenancy + 1.0 + diff --git a/mallinkCApi/pom.xml b/mallinkCApi/pom.xml index 7935ee17e..647618dbc 100644 --- a/mallinkCApi/pom.xml +++ b/mallinkCApi/pom.xml @@ -18,8 +18,9 @@ 1.0 - junit - junit + com.iformall + mybatis-multi-tenancy + 1.0 diff --git a/mallinkService/pom.xml b/mallinkService/pom.xml index 5f7a6419c..2ea9abea7 100644 --- a/mallinkService/pom.xml +++ b/mallinkService/pom.xml @@ -10,4 +10,14 @@ 4.0.0 mallinkService + \ No newline at end of file diff --git a/mybatis-multi-tenancy/pom.xml b/mybatis-multi-tenancy/pom.xml new file mode 100644 index 000000000..19c112f64 --- /dev/null +++ b/mybatis-multi-tenancy/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + com.iformall + mybatis-multi-tenancy + 1.0 + + + com.github.jsqlparser + jsqlparser + 1.3 + compile + + + org.mybatis + mybatis + 3.4.6 + compile + + + + test + junit + junit + 4.12 + + + test + mysql + mysql-connector-java + 8.0.11 + + + test + com.alibaba + druid + 1.1.11 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + utf-8 + + + + maven-source-plugin + 2.4 + + + package + + jar-no-fork + + + + + + + maven-surefire-plugin + 2.9 + + + false + + once + -Dfile.encoding=UTF-8 + + + + + + \ No newline at end of file diff --git a/mybatis-multi-tenancy/src/main/java/com/iformall/plugin/MultiTenancy.java b/mybatis-multi-tenancy/src/main/java/com/iformall/plugin/MultiTenancy.java new file mode 100644 index 000000000..afef9d6fe --- /dev/null +++ b/mybatis-multi-tenancy/src/main/java/com/iformall/plugin/MultiTenancy.java @@ -0,0 +1,553 @@ +package com.iformall.plugin; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.BinaryExpression; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.EqualsTo; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; +import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.schema.Table; +import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.statement.create.table.ColDataType; +import net.sf.jsqlparser.statement.create.table.ColumnDefinition; +import net.sf.jsqlparser.statement.create.table.CreateTable; +import net.sf.jsqlparser.statement.delete.Delete; +import net.sf.jsqlparser.statement.insert.Insert; +import net.sf.jsqlparser.statement.select.*; +import net.sf.jsqlparser.statement.update.Update; +import net.sf.jsqlparser.util.TablesNamesFinder; +import org.apache.ibatis.executor.statement.StatementHandler; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlCommandType; +import org.apache.ibatis.plugin.*; +import org.apache.ibatis.reflection.MetaObject; +import org.apache.ibatis.reflection.SystemMetaObject; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.session.ResultHandler; + +import java.sql.Connection; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; + +/** + *共享数据库的多租户系统实现 + * TODO 白名单模式 + * TODO 黑名单模式 + * Created by kleen@qq.com on 2016/08/13. + */ +@Intercepts({ + //@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}), + //@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}) + @Signature( method = "prepare", type = StatementHandler.class,args = {Connection.class, Integer.class}), + @Signature(method = "query", type = StatementHandler.class, args = {java.sql.Statement.class, ResultHandler.class}) +}) +public class MultiTenancy implements Interceptor { + + //获取tenantId的接口 + private TenantInfo tenantInfo; + private String tenantIdColumn = "tenant_id"; + private String dialect = "mysql"; + //属性参数信息 + private Properties properties; + + public MultiTenancy(){ + } + + public Object intercept(Invocation invocation) throws Throwable { + if (getTenantInfo().getTenantId() != null) { + // 能从cookie或者session获取到tenantId + mod(invocation); + } + return invocation.proceed(); + } + + /** + * 更改MappedStatement为新的 + * @param invocation + * @throws Throwable + */ + public void mod(Invocation invocation) throws Throwable { + StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); + MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler); + Configuration configuration = (Configuration) metaStatementHandler.getValue("delegate.configuration"); + + MappedStatement ms = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement"); + if (getTenantInfo().doMappedStatementFIlter(ms)) + return; + SqlCommandType type = ms.getSqlCommandType(); + + BoundSql boundSql = statementHandler.getBoundSql(); + + String newSQL = addWhere(boundSql.getSql()); + if (newSQL != null) { + metaStatementHandler.setValue("delegate.boundSql.sql", newSQL); + } + + } + + /** + * 添加租户id条件 + * @param sql + * @return + * @throws JSQLParserException + */ + private String addWhere(String sql) throws Exception { + Statement stmt = CCJSqlParserUtil.parse(sql); + if (stmt instanceof Insert) { + //获得Insert对象 + Insert insert = (Insert) stmt; + if (getTenantInfo().doTableFilter(insert.getTable().getName())) + return insert.toString(); + boolean bExist = false; + for(Column col:insert.getColumns()) { + if(col.getColumnName().equalsIgnoreCase(getTenantIdColumn())) + bExist = true; + } + if (!bExist) { + insert.getColumns().add(new Column(getTenantIdColumn())); + + if (insert.getItemsList() instanceof MultiExpressionList){ + for (ExpressionList expressionList : ((MultiExpressionList) insert.getItemsList()).getExprList()) { + addTenantValue(expressionList); + } + }else { + addTenantValue(((ExpressionList) insert.getItemsList())); + } + } + return insert.toString(); + } + + if (stmt instanceof Delete) { + //获得Delete对象 + Delete deleteStatement = (Delete) stmt; + if (getTenantInfo().doTableFilter(deleteStatement.getTable().getName())) + return deleteStatement.toString(); + Expression where = deleteStatement.getWhere(); + if (where instanceof BinaryExpression) { + EqualsTo equalsTo = new EqualsTo(); + equalsTo.setLeftExpression(new Column(getTenantIdColumn())); + equalsTo.setRightExpression(new StringValue(getTenantInfo().getTenantId())); + AndExpression andExpression = new AndExpression(equalsTo, where); + deleteStatement.setWhere(andExpression); + } + return deleteStatement.toString(); + } + + if (stmt instanceof Update) { + //获得Update对象 + Update updateStatement = (Update) stmt; + TablesNamesFinder tablesNamesFinder = new TablesNamesFinder(); + List tableList = tablesNamesFinder.getTableList(stmt); + if (tableList.size() == 0) { + return updateStatement.toString(); + } + //获得where条件表达式 + Expression where = updateStatement.getWhere(); + for (String table: tableList) { + if (getTenantInfo().doTableFilter(table)) + continue; + if (where != null) { + updateStatement.setWhere(addAndExpression(stmt, table, updateStatement.getWhere())); + } else { + throw new Exception("update语句不能没有where条件:" + sql + Arrays.toString(Thread.currentThread().getStackTrace())); + } + } + return updateStatement.toString(); + } + + if (stmt instanceof Select) { + //获得Select对象 + Select select = (Select) stmt; + PlainSelect ps = (PlainSelect) select.getSelectBody(); + TablesNamesFinder tablesNamesFinder = new TablesNamesFinder(); + List tableList = tablesNamesFinder.getTableList(select); + + if (tableList.size() == 0) { + return select.toString(); + } + for (String table : tableList) { + if (getTenantInfo().doTableFilter(table)) + continue; + if (ps.getWhere() != null) { + AndExpression where = addAndExpression(stmt, table, ps.getWhere()); + // form 和 join 中加载的表 + if (where != null) { + ps.setWhere(where); + } else { + //子查询中的表 + findSubSelect(stmt, ps.getWhere()); + } + } else { + ps.setWhere(addEqualsTo(stmt, table)); + } + } + return select.toString(); + } + + if (stmt instanceof CreateTable) { + CreateTable createTable = (CreateTable) stmt; + ColumnDefinition columnDefinition = new ColumnDefinition(); + columnDefinition.setColumnName(getTenantIdColumn()); + ColDataType colDataType = new ColDataType(); + colDataType.setDataType("varchar(50)"); + columnDefinition.setColDataType(colDataType); + createTable.getColumnDefinitions().add(columnDefinition); + return createTable.toString(); + } + throw new RuntimeException("非法sql语句,请检查"+sql); + } + + /** + * 生成代理对象 + * + * @param target + * @return + */ + @Override + public Object plugin(Object target) { + if (target instanceof StatementHandler) { + return Plugin.wrap(target, this); + } else { + return target; + } + } + + /** + * 获取配置信息 + * {dialect=mysql, tenantInfo=org.xue.test.TenantInfoImpl, tenantIdColumn=tenant_id} + * @param properties + */ + public void setProperties(Properties properties) { + this.properties=properties; + try { + Class onwClass=Class.forName(this.properties.getProperty("tenantInfo")); + this.tenantInfo = (TenantInfo)onwClass.newInstance(); + this.tenantIdColumn = this.properties.getProperty("tenantIdColumn"); + this.dialect = this.properties.getProperty("dialect"); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + /** + * 插入数据 添加租户id + * @param expressionList + * @throws Exception + */ + private void addTenantValue(ExpressionList expressionList) throws Exception { + expressionList.getExpressions().add(new StringValue(getTenantInfo().getTenantId())); + } + + /** + * 多条件情况下,使用AndExpression给where条件加上tenantid条件 + * + * @param table + * @param where + * @return + * @throws Exception + */ + public AndExpression addAndExpression(Statement stmt, String table, Expression where) throws Exception { + EqualsTo equalsTo = addEqualsTo(stmt, table); + if (equalsTo != null) { + return new AndExpression(equalsTo, where); + } else { + return null; + } + } + + /** + * 创建一个 EqualsTo相同判断 条件 + * + * @param stmt 查询对象 + * @param table 表名 + * @return “A=B” 单个where条件表达式 + * @throws Exception + */ + public EqualsTo addEqualsTo(Statement stmt, String table) throws Exception { + EqualsTo equalsTo = new EqualsTo(); + String aliasName; + aliasName = getTableAlias(stmt, table); + if (aliasName != null) { + equalsTo.setLeftExpression(new Column(aliasName + '.' + getTenantIdColumn())); + equalsTo.setRightExpression(new StringValue(getTenantInfo().getTenantId())); + return equalsTo; + } else { + return null; + } + } + + /** + * 获取sql送指定表的别名你,没有别名则返回原表名 如果表名不存在返回null + * 【仅查询from和join 不含 IN 子查询中的表 】 + * + * @param stmt + * @param tableName + * @return + */ + public String getTableAlias(Statement stmt, String tableName) { + String alias = null; + + // 插入不做处理 + if (stmt instanceof Insert) { + return tableName; + } + + if (stmt instanceof Delete) { + //获得Delete对象 + Delete deleteStatement = (Delete) stmt; + + if ((deleteStatement.getTable()).getName().equalsIgnoreCase(tableName)) { + alias = deleteStatement.getTable().getAlias() != null ? deleteStatement.getTable().getAlias().getName() : tableName; + } + } + + if (stmt instanceof Update) { + //获得Update对象 + Update updateStatement = (Update) stmt; + + if ((updateStatement.getTables().get(0)).getName().equalsIgnoreCase(tableName)) { + alias = updateStatement.getTables().get(0).getAlias() != null ? updateStatement.getTables().get(0).getAlias().getName() : tableName; + } + } + + if (stmt instanceof Select) { + Select select = (Select) stmt; + + PlainSelect ps = (PlainSelect) select.getSelectBody(); + FromItem item = ps.getFromItem(); + + // 判断主表的别名 + if (item instanceof Table) { + if (((Table) item).getName().equalsIgnoreCase(tableName)) { + alias = item.getAlias() != null ? item.getAlias().getName() : tableName; + } + } else { + + } + } + return alias; + } + + /** + * 针对子查询中的表别名查询 + * + * @param subSelect + * @param tableName + * @return + */ + public String getTableAlias(SubSelect subSelect, String tableName) { + PlainSelect ps = (PlainSelect) subSelect.getSelectBody(); + // 判断主表的别名 + String alias = null; + FromItem item = ps.getFromItem(); + if (item instanceof Table) { + if (((Table) item).getName().equalsIgnoreCase(tableName)){ + if (item.getAlias() != null) { + alias = item.getAlias().getName(); + } else { + alias = tableName; + } + } + } + return alias; + } + + /** + * 递归处理 子查询中的tenantid-where + * + * @param stmt sql查询对象 + * @param where 当前sql的where条件 where为AndExpression或OrExpression的实例,解析其中的rightExpression,然后检查leftExpression是否为空, + * 不为空则是AndExpression或OrExpression,再次解析其中的rightExpression + * 注意tenantid-where是加在子查询上的 + */ + void findSubSelect(Statement stmt, Expression where) throws Exception { + + // and 表达式 + if (where instanceof AndExpression) { + AndExpression andExpression = (AndExpression) where; + if (andExpression.getRightExpression() instanceof SubSelect) { + SubSelect subSelect = (SubSelect) andExpression.getRightExpression(); + doSelect(stmt, subSelect); + } + if (andExpression.getLeftExpression() != null) { + findSubSelect(stmt, andExpression.getLeftExpression()); + } + } else if (where instanceof OrExpression) { + // or表达式 + OrExpression orExpression = (OrExpression) where; + if (orExpression.getRightExpression() instanceof SubSelect) { + SubSelect subSelect = (SubSelect) orExpression.getRightExpression(); + doSelect(stmt, subSelect); + } + if (orExpression.getLeftExpression() != null) { + findSubSelect(stmt, orExpression.getLeftExpression()); + } + } + } + + /** + * 处理select 和 subSelect + * + * @param stmt 查询对象 + * @param select + * @return + * @throws Exception + */ + Expression doSelect(Statement stmt, Expression select) throws Exception { + PlainSelect ps = null; + boolean hasSubSelect = false; + + if (select instanceof SubSelect) { + ps = (PlainSelect) ((SubSelect) select).getSelectBody(); + } + if (select instanceof Select) { + ps = (PlainSelect) ((Select) select).getSelectBody(); + } + + TablesNamesFinder tablesNamesFinder = new TablesNamesFinder(); + List tableList = tablesNamesFinder.getTableList(select); + if (tableList.size() == 0) { + return select; + } + for (String table : tableList) { + // sql 包含 where 条件的情况 使用 addAndExpression 连接 已有的条件和新条件 + if (ps.getWhere() == null) { + AndExpression where = addAndExpression(stmt, table, ps.getWhere()); + // form 和 join 中加载的表 + if (where != null) { + ps.setWhere(where); + } else { + // 如果在Statement中不存在这个表名,则存在于子查询中 + hasSubSelect = true; + } + } else { + // sql 不含 where条件 新建一个EqualsTo设置为where条件 + EqualsTo equalsTo = addEqualsTo(stmt, table); + ps.setWhere(equalsTo); + } + } + + if (hasSubSelect) { + //子查询中的表 + findSubSelect(stmt, ps.getWhere()); + } + return select; + } + + private void processSelectBody(SelectBody selectBody) { + if (selectBody instanceof PlainSelect) { + processPlainSelect((PlainSelect) selectBody); + } else if (selectBody instanceof WithItem) { + WithItem withItem = (WithItem) selectBody; + if (withItem.getSelectBody() != null) { + processSelectBody(withItem.getSelectBody()); + } + } else { + SetOperationList operationList = (SetOperationList) selectBody; + if (operationList.getOperations() != null && operationList.getSelects().size() > 0) { + List plainSelects = operationList.getSelects(); + for (SelectBody sub: plainSelects) { + processSelectBody(sub); + } + } + if (!orderByHashParameters(operationList.getOrderByElements())) { + operationList.setOrderByElements(null); + } + } + } + + private void processPlainSelect(PlainSelect plainSelect) { + if (!orderByHashParameters(plainSelect.getOrderByElements())) { + plainSelect.setOrderByElements(null); + } + if (plainSelect.getFromItem() != null) { + processFromItem(plainSelect.getFromItem()); + } + if (plainSelect.getJoins() != null && plainSelect.getJoins().size() > 0) { + List joins = plainSelect.getJoins(); + for (Join join : joins) { + if (join.getRightItem() != null) { + processFromItem(join.getRightItem()); + } + } + } + } + + public void processFromItem(FromItem fromItem) { + if (fromItem instanceof SubJoin) { + SubJoin subJoin = (SubJoin) fromItem; + if (subJoin.getJoinList() != null) { + for(Join tjoin: subJoin.getJoinList()) { + if (tjoin.getRightItem() != null) { + processFromItem(tjoin.getRightItem()); + } + } + } + } else if (fromItem instanceof SubSelect) { + SubSelect subSelect = (SubSelect) fromItem; + if (subSelect.getSelectBody() != null) { + processSelectBody(subSelect.getSelectBody()); + } + } else if (fromItem instanceof ValuesList) { + + } else if (fromItem instanceof LateralSubSelect) { + LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem; + if (lateralSubSelect.getSubSelect() != null) { + SubSelect subSelect = (SubSelect) (lateralSubSelect.getSubSelect()); + if (subSelect.getSelectBody() != null) { + processSelectBody(subSelect.getSelectBody()); + } + } + } + //Table时不用处理 + } + + public boolean orderByHashParameters(List orderByElements) { + if (orderByElements == null) { + return false; + } + for (OrderByElement orderByElement : orderByElements) { + if (orderByElement.toString().toUpperCase().contains("?")) { + return true; + } + } + return false; + } + + public TenantInfo getTenantInfo() { + return tenantInfo; + } + + public void setTenantInfo(TenantInfo tenantInfo) { + this.tenantInfo = tenantInfo; + } + + public String getTenantIdColumn() { + return tenantIdColumn; + } + + public void setTenantIdColumn(String tenantIdColumn) { + this.tenantIdColumn = tenantIdColumn; + } + + public String getDialect() { + return dialect; + } + + public void setDialect(String dialect) { + this.dialect = dialect; + } + + +} diff --git a/mybatis-multi-tenancy/src/main/java/com/iformall/plugin/TenantInfo.java b/mybatis-multi-tenancy/src/main/java/com/iformall/plugin/TenantInfo.java new file mode 100644 index 000000000..33c6a546e --- /dev/null +++ b/mybatis-multi-tenancy/src/main/java/com/iformall/plugin/TenantInfo.java @@ -0,0 +1,15 @@ +package com.iformall.plugin; + +import org.apache.ibatis.mapping.MappedStatement; + +/** + * 需要实现该接口用于获取租户id + * Created by kleen@qq.com on 2016/08/13. + */ +public interface TenantInfo { + String getTenantId(); + + boolean doTableFilter(String tableName); + + boolean doMappedStatementFIlter(MappedStatement ms); +} diff --git a/mybatis-multi-tenancy/src/test/java/com/iformall/plugin/TenantInfoImpl.java b/mybatis-multi-tenancy/src/test/java/com/iformall/plugin/TenantInfoImpl.java new file mode 100644 index 000000000..5e7d212de --- /dev/null +++ b/mybatis-multi-tenancy/src/test/java/com/iformall/plugin/TenantInfoImpl.java @@ -0,0 +1,24 @@ +package com.iformall.plugin; + +import org.apache.ibatis.mapping.MappedStatement; + +/** + * 自行实现TenantInfo获取 + * Created by Meara on 2016/3/20. + */ +public class TenantInfoImpl implements TenantInfo{ + @Override + public String getTenantId() { + return "2"; + } + + @Override + public boolean doTableFilter(String tableName) { + return false; + } + + @Override + public boolean doMappedStatementFIlter(MappedStatement ms) { + return false; + } +} diff --git a/mybatis-multi-tenancy/src/test/java/com/iformall/plugin/mapper/BookMapper.java b/mybatis-multi-tenancy/src/test/java/com/iformall/plugin/mapper/BookMapper.java new file mode 100644 index 000000000..0efa365cc --- /dev/null +++ b/mybatis-multi-tenancy/src/test/java/com/iformall/plugin/mapper/BookMapper.java @@ -0,0 +1,11 @@ +package com.iformall.plugin.mapper; + +import java.util.List; +import java.util.Map; + +/** + * Created by Meara on 2016/3/17. + */ +public interface BookMapper { + List selectAll(); +} diff --git a/mybatis-multi-tenancy/src/test/java/com/iformall/plugin/mapper/UserMapper.java b/mybatis-multi-tenancy/src/test/java/com/iformall/plugin/mapper/UserMapper.java new file mode 100644 index 000000000..138a94f97 --- /dev/null +++ b/mybatis-multi-tenancy/src/test/java/com/iformall/plugin/mapper/UserMapper.java @@ -0,0 +1,15 @@ +package com.iformall.plugin.mapper; + +import java.util.List; +import java.util.Map; + +/** + * Created by Meara on 2016/3/17. + */ +public interface UserMapper { + List selectAll(); + List selectWhere(Long id); + void update(); + + void insert(Map map); +} diff --git a/mybatis-multi-tenancy/src/test/java/com/iformall/plugin/test/MybatisTest.java b/mybatis-multi-tenancy/src/test/java/com/iformall/plugin/test/MybatisTest.java new file mode 100644 index 000000000..7ca385438 --- /dev/null +++ b/mybatis-multi-tenancy/src/test/java/com/iformall/plugin/test/MybatisTest.java @@ -0,0 +1,32 @@ +package com.iformall.plugin.test; + +import com.iformall.plugin.mapper.UserMapper; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.junit.Test; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +/** + * Created by Meara on 2016/3/17. + */ +public class MybatisTest { + @Test + public void query(){ + InputStream is = MybatisTest.class.getClassLoader().getResourceAsStream("mybatisConf.xml"); + SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); + SqlSession session= sqlSessionFactory.openSession(); + UserMapper userDao = session.getMapper(UserMapper.class); + + Map map = new HashMap(); + map.put("uid",8); + map.put("username","kleen"); + map.put("password","123"); + + userDao.insert(map); + session.commit(); + } +} diff --git a/mybatis-multi-tenancy/src/test/resources/com/iformall/plugin/mapper/BookMapper.xml b/mybatis-multi-tenancy/src/test/resources/com/iformall/plugin/mapper/BookMapper.xml new file mode 100644 index 000000000..561bbb832 --- /dev/null +++ b/mybatis-multi-tenancy/src/test/resources/com/iformall/plugin/mapper/BookMapper.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/mybatis-multi-tenancy/src/test/resources/com/iformall/plugin/mapper/UserMapper.xml b/mybatis-multi-tenancy/src/test/resources/com/iformall/plugin/mapper/UserMapper.xml new file mode 100644 index 000000000..f0deb66be --- /dev/null +++ b/mybatis-multi-tenancy/src/test/resources/com/iformall/plugin/mapper/UserMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + update user set password = '李鉴新1' where password='fred'; + + + + INSERT INTO user(uid,username,password)VALUES(#{uid},#{username},#{password}); + + \ No newline at end of file diff --git a/mybatis-multi-tenancy/src/test/resources/mybatisConf.xml b/mybatis-multi-tenancy/src/test/resources/mybatisConf.xml new file mode 100644 index 000000000..48e4dbaf1 --- /dev/null +++ b/mybatis-multi-tenancy/src/test/resources/mybatisConf.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mybatis-multi-tenancy/src/test/resources/test-init.sql b/mybatis-multi-tenancy/src/test/resources/test-init.sql new file mode 100644 index 000000000..b4d84d6a8 --- /dev/null +++ b/mybatis-multi-tenancy/src/test/resources/test-init.sql @@ -0,0 +1,31 @@ +DROP TABLE IF EXISTS `book`; +CREATE TABLE `book` ( + `bid` bigint(20) NOT NULL AUTO_INCREMENT, + `bookname` varchar(255) NOT NULL, + `tenant_id` int(11) NOT NULL, + PRIMARY KEY (`bid`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Records of book +-- ---------------------------- +INSERT INTO `book` VALUES ('1', '三国演义', '1'); +INSERT INTO `book` VALUES ('2', '西游记', '2'); + +-- ---------------------------- +-- Table structure for user +-- ---------------------------- +DROP TABLE IF EXISTS `user`; +CREATE TABLE `user` ( + `uid` bigint(20) NOT NULL AUTO_INCREMENT, + `username` varchar(255) NOT NULL, + `password` varchar(255) NOT NULL, + `tenant_id` int(11) NOT NULL, + PRIMARY KEY (`uid`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; + +-- ---------------------------- +-- Records of user +-- ---------------------------- +INSERT INTO `user` VALUES ('1', 'root', '123', '1'); +INSERT INTO `user` VALUES ('2', 'user', '123', '2'); \ No newline at end of file diff --git a/pom.xml b/pom.xml index 32cbeea19..22d5fed14 100644 --- a/pom.xml +++ b/pom.xml @@ -11,10 +11,12 @@ 1.0 + mybatis-multi-tenancy mallinkService mallinkAdmin mallinkCApi mallinkBApi + mallinkSchedule