Browse Source

meta object handler enhance

yuxiaobin 8 years ago
parent
commit
3f22492ab2

+ 12 - 8
mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisDefaultParameterHandler.java

@@ -129,7 +129,17 @@ public class MybatisDefaultParameterHandler extends DefaultParameterHandler {
                 }
                 return objList;
             } else {
-                TableInfo tableInfo = TableInfoHelper.getTableInfo(parameterObject.getClass());
+                TableInfo tableInfo;
+                if(parameterObject instanceof java.util.Map){
+                    Object et = ((java.util.Map)parameterObject).get("et");
+                    if(et!=null){
+                        tableInfo = TableInfoHelper.getTableInfo(et.getClass());
+                    }else{
+                        tableInfo = null;
+                    }
+                }else{
+                    tableInfo = TableInfoHelper.getTableInfo(parameterObject.getClass());
+                }
                 return populateKeys(metaObjectHandler, tableInfo, ms, parameterObject);
             }
         }
@@ -226,13 +236,7 @@ public class MybatisDefaultParameterHandler extends DefaultParameterHandler {
                 if (parameterMapping.getMode() != ParameterMode.OUT) {
                     Object value;
                     String propertyName = parameterMapping.getProperty();
-                    if (boundSql.hasAdditionalParameter(propertyName)) { // issue
-                        // #448
-                        // ask
-                        // first
-                        // for
-                        // additional
-                        // params
+                    if (boundSql.hasAdditionalParameter(propertyName)) {//issue#448 ask first for additional params
                         value = boundSql.getAdditionalParameter(propertyName);
                     } else if (parameterObject == null) {
                         value = null;

+ 48 - 0
mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/MetaObjectHandler.java

@@ -27,6 +27,8 @@ import org.apache.ibatis.reflection.MetaObject;
  */
 public abstract class MetaObjectHandler {
 
+    protected static final String META_OBJ_PREFIX = "et";
+
     /**
      * <p>
      * 插入元对象字段填充
@@ -47,6 +49,52 @@ public abstract class MetaObjectHandler {
      */
     public abstract void updateFill(MetaObject metaObject);
 
+    /**
+     * Common method to set value for java bean.
+     *
+     * @param fieldName java bean property name
+     * @param fieldVal  java bean property value
+     * @param metaObject meta object parameter
+     */
+    public MetaObjectHandler setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject){
+        String[] fieldNames = metaObject.getGetterNames();
+        boolean containsEt = false;
+        for(String name:fieldNames){
+            if(META_OBJ_PREFIX.equals(name)){
+                containsEt = true;
+                break;
+            }
+        }
+        if(containsEt) {
+            metaObject.setValue(META_OBJ_PREFIX +"."+ fieldName, fieldVal);
+        }else{
+            metaObject.setValue(fieldName, fieldVal);
+        }
+        return this;
+    }
+
+    /**
+     * get value from java bean by propertyName
+     * @param fieldName java bean property name
+     * @param metaObject parameter wrapper
+     * @return
+     */
+    public Object getFieldValByName(String fieldName, MetaObject metaObject){
+        String[] fieldNames = metaObject.getGetterNames();
+        boolean containsEt = false;
+        for(String name:fieldNames){
+            if(META_OBJ_PREFIX.equals(name)){
+                containsEt = true;
+                break;
+            }
+        }
+        if(containsEt) {
+            return metaObject.getValue(META_OBJ_PREFIX +"."+ fieldName);
+        }else{
+            return metaObject.getValue(fieldName);
+        }
+    }
+
     /**
      * 开启插入填充
      */

+ 117 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/H2MetaObjectHandlerTest.java

@@ -0,0 +1,117 @@
+package com.baomidou.mybatisplus.test.h2;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+import javax.sql.DataSource;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import com.baomidou.mybatisplus.test.h2.entity.mapper.H2UserMetaobjMapper;
+import com.baomidou.mybatisplus.test.h2.entity.persistent.H2UserMetaObj;
+
+/**
+ * <p>
+ * TODO class
+ * </p>
+ *
+ * @author yuxiaobin
+ * @date 2017/5/31
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {"classpath:h2/spring-test-h2-metaobj.xml"})
+public class H2MetaObjectHandlerTest {
+
+    @BeforeClass
+    public static void initDB() throws SQLException, IOException {
+        @SuppressWarnings("resource")
+        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:h2/spring-test-h2-metaobj.xml");
+        DataSource ds = (DataSource) context.getBean("dataSource");
+        try (Connection conn = ds.getConnection()) {
+            String createTableSql = readFile("user.ddl.sql");
+            Statement stmt = conn.createStatement();
+            stmt.execute(createTableSql);
+            stmt.execute("truncate table h2user");
+            insertUsers(stmt);
+            conn.commit();
+        }
+    }
+
+    private static void insertUsers(Statement stmt) throws SQLException, IOException {
+        String filename = "user.insert.sql";
+        String filePath = H2UserTest.class.getClassLoader().getResource("").getPath() + "/h2/" + filename;
+        try (
+                BufferedReader reader = new BufferedReader(new FileReader(filePath))
+        ) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                stmt.execute(line.replace(";", ""));
+            }
+        }
+    }
+
+    private static String readFile(String filename) {
+        StringBuilder builder = new StringBuilder();
+        String filePath = H2UserTest.class.getClassLoader().getResource("").getPath() + "/h2/" + filename;
+        try (
+                BufferedReader reader = new BufferedReader(new FileReader(filePath))
+        ) {
+            String line;
+            while ((line = reader.readLine()) != null)
+                builder.append(line).append(" ");
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return builder.toString();
+    }
+
+    @Autowired
+    H2UserMetaobjMapper userMapper;
+
+    @Test
+    public void testMetaObjectHandler(){
+        H2UserMetaObj user = new H2UserMetaObj();
+        user.setName("metaobjtest");
+        user.setVersion(1);
+        user.setAge(12);
+        Calendar cal = Calendar.getInstance();
+        cal.add(Calendar.DAY_OF_MONTH,-1);
+        user.setLastUpdatedDt(new Timestamp(cal.getTimeInMillis()));
+        user.setDesc("abc");
+        userMapper.insert(user);
+        System.out.println("before update: getLastUpdatedDt=" + user.getLastUpdatedDt());
+
+        user.setName("999");
+        userMapper.updateById(user);
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH");
+        Long id = user.getId();
+        H2UserMetaObj userDB = userMapper.selectById(id);
+
+        //MyMetaObjectHandler.insertFill() : set default testType value=3
+        Assert.assertEquals(3, userDB.getTestType().intValue());
+        Assert.assertEquals("999", userDB.getName());
+
+        Date lastUpdatedDt = userDB.getLastUpdatedDt();
+        System.out.println("after update: testDate=" + lastUpdatedDt);
+        String versionDateStr = sdf.format(lastUpdatedDt);
+        //MyMetaObjectHandler.updateFill() : set 
+        Assert.assertEquals(sdf.format(new Date()), versionDateStr);
+    }
+
+}

+ 104 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/H2UserAutoincrementTest.java

@@ -0,0 +1,104 @@
+package com.baomidou.mybatisplus.test.h2;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import javax.sql.DataSource;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import com.baomidou.mybatisplus.test.h2.entity.mapper.H2UserMetaobjMapper;
+import com.baomidou.mybatisplus.test.h2.entity.persistent.H2UserMetaObj;
+
+/**
+ * <p>
+ * Mybatis Plus H2 Junit Test
+ * </p>
+ *
+ * @author Caratacus
+ * @date 2017/4/1
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {"classpath:h2/spring-test-h2.xml"})
+public class H2UserAutoincrementTest {
+
+    @Autowired
+    private H2UserMetaobjMapper userMapper;
+
+    @BeforeClass
+    public static void initDB() throws SQLException, IOException {
+        @SuppressWarnings("resource")
+        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:h2/spring-test-h2.xml");
+        DataSource ds = (DataSource) context.getBean("dataSource");
+        try (Connection conn = ds.getConnection()) {
+            String createTableSql = readFile("user.ddl.sql");
+            Statement stmt = conn.createStatement();
+            stmt.execute(createTableSql);
+            stmt.execute("truncate table h2user");
+            insertUsers(stmt);
+            conn.commit();
+        }
+    }
+
+    private static void insertUsers(Statement stmt) throws SQLException, IOException {
+        String filename = "user.insert.sql";
+        String filePath = H2UserAutoincrementTest.class.getClassLoader().getResource("").getPath() + "/h2/" + filename;
+        try (
+                BufferedReader reader = new BufferedReader(new FileReader(filePath))
+        ) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                stmt.execute(line.replace(";", ""));
+            }
+        }
+    }
+
+    private static String readFile(String filename) {
+        StringBuilder builder = new StringBuilder();
+        String filePath = H2UserAutoincrementTest.class.getClassLoader().getResource("").getPath() + "/h2/" + filename;
+        try (
+                BufferedReader reader = new BufferedReader(new FileReader(filePath))
+        ) {
+            String line;
+            while ((line = reader.readLine()) != null)
+                builder.append(line).append(" ");
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return builder.toString();
+    }
+
+    @Test
+    public void testInsert() {
+        H2UserMetaObj user = new H2UserMetaObj();
+        user.setAge(1);
+        user.setPrice(new BigDecimal("9.99"));
+        Assert.assertEquals(1, userMapper.insert(user).intValue());
+        Long id1 = user.getId();
+        Assert.assertNotNull(id1);
+        user.setDesc("Caratacus");
+        Assert.assertEquals(1, userMapper.updateById(user).intValue());
+        H2UserMetaObj userFromDB = userMapper.selectById(id1);
+        Assert.assertEquals("Caratacus", userFromDB.getDesc());
+
+        H2UserMetaObj user2 = new H2UserMetaObj();
+        user2.setAge(2);
+        Assert.assertEquals(1, userMapper.insert(user2).intValue());
+        Long userId2 = user2.getId();
+        Assert.assertEquals(id1.intValue()+1, userId2.intValue());
+    }
+
+}

+ 57 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/config/MybatisPlusMetaObjConfig.java

@@ -0,0 +1,57 @@
+package com.baomidou.mybatisplus.test.h2.config;
+
+import javax.sql.DataSource;
+
+import org.apache.ibatis.plugin.Interceptor;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.type.JdbcType;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ResourceLoader;
+
+import com.baomidou.mybatisplus.MybatisConfiguration;
+import com.baomidou.mybatisplus.MybatisXMLLanguageDriver;
+import com.baomidou.mybatisplus.entity.GlobalConfiguration;
+import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
+import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
+import com.baomidou.mybatisplus.test.mysql.MyMetaObjectHandler;
+
+/**
+ * <p>
+ * Mybatis Plus Config without OptimisLock
+ * </p>
+ *
+ * @author Caratacus
+ * @date 2017/4/1
+ */
+@Configuration
+@MapperScan("com.baomidou.mybatisplus.test.h2.entity.mapper")
+public class MybatisPlusMetaObjConfig {
+
+    @Bean("mybatisSqlSession")
+    public SqlSessionFactory sqlSessionFactory(DataSource dataSource, ResourceLoader resourceLoader, GlobalConfiguration globalConfiguration) throws Exception {
+        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
+        sqlSessionFactory.setDataSource(dataSource);
+//        sqlSessionFactory.setConfigLocation(resourceLoader.getResource("classpath:mybatis-config.xml"));
+        sqlSessionFactory.setTypeAliasesPackage("com.baomidou.mybatisplus.test.h2.entity.persistent");
+        MybatisConfiguration configuration = new MybatisConfiguration();
+        configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
+        configuration.setJdbcTypeForNull(JdbcType.NULL);
+        sqlSessionFactory.setConfiguration(configuration);
+        PaginationInterceptor pagination = new PaginationInterceptor();
+        sqlSessionFactory.setPlugins(new Interceptor[]{
+                pagination,
+        });
+        sqlSessionFactory.setGlobalConfig(globalConfiguration);
+        return sqlSessionFactory.getObject();
+    }
+
+    @Bean
+    public GlobalConfiguration globalConfiguration() {
+        GlobalConfiguration globalConfiguration = new GlobalConfiguration();
+        globalConfiguration.setIdType(2);
+        globalConfiguration.setMetaObjectHandler(new MyMetaObjectHandler());
+        return globalConfiguration;
+    }
+}

+ 15 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/entity/mapper/H2UserMetaobjMapper.java

@@ -0,0 +1,15 @@
+package com.baomidou.mybatisplus.test.h2.entity.mapper;
+
+import com.baomidou.mybatisplus.mapper.BaseMapper;
+import com.baomidou.mybatisplus.test.h2.entity.persistent.H2UserMetaObj;
+
+/**
+ * <p>
+ * </p>
+ *
+ * @author Caratacus
+ * @date 2017/4/1
+ */
+public interface H2UserMetaobjMapper extends BaseMapper<H2UserMetaObj> {
+
+}

+ 185 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/entity/persistent/H2UserMetaObj.java

@@ -0,0 +1,185 @@
+/**
+ * Copyright (c) 2011-2014, hubin (jobob@qq.com).
+ * <p>
+ * Licensed 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 com.baomidou.mybatisplus.test.h2.entity.persistent;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+
+import com.baomidou.mybatisplus.annotations.TableField;
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.annotations.TableName;
+import com.baomidou.mybatisplus.annotations.Version;
+import com.baomidou.mybatisplus.enums.FieldStrategy;
+import com.baomidou.mybatisplus.enums.IdType;
+
+/**
+ * <p>
+ * 测试用户类
+ * </p>
+ *
+ * @author hubin sjy
+ */
+/* 表名 value 注解【 驼峰命名可无 】, resultMap 注解测试【 映射 xml 的 resultMap 内容 】 */
+@TableName("h2user")
+public class H2UserMetaObj implements Serializable {
+
+    /* 表字段注解,false 表中不存在的字段,可无该注解 默认 true */
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+
+    /* 主键ID 注解,value 字段名,type 用户输入ID */
+    @TableId(value = "test_id", type = IdType.AUTO)
+    private Long id;
+
+    /* 测试忽略验证 */
+    private String name;
+
+    private Integer age;
+
+    /*BigDecimal 测试*/
+    private BigDecimal price;
+
+    /* 测试下划线字段命名类型, 字段填充 */
+    @TableField(value = "test_type", validate = FieldStrategy.IGNORED)
+    private Integer testType;
+
+    private String desc;
+
+    @Version
+    private Integer version;
+    @TableField(value = "last_updated_dt")
+    private Timestamp lastUpdatedDt;
+
+
+    public H2UserMetaObj() {
+
+    }
+
+    public H2UserMetaObj(String name) {
+        this.name = name;
+    }
+
+    public H2UserMetaObj(Integer testType) {
+        this.testType = testType;
+    }
+
+    public H2UserMetaObj(String name, Integer age) {
+        this.name = name;
+        this.age = age;
+    }
+
+    public H2UserMetaObj(Long id, String name) {
+        this.id = id;
+        this.name = name;
+    }
+
+    public H2UserMetaObj(Long id, Integer age) {
+        this.id = id;
+        this.age = age;
+    }
+
+    public H2UserMetaObj(Long id, String name, Integer age, Integer testType) {
+        this.id = id;
+        this.name = name;
+        this.age = age;
+        this.testType = testType;
+    }
+
+    public H2UserMetaObj(String name, Integer age, Integer testType) {
+        this.name = name;
+        this.age = age;
+        this.testType = testType;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public BigDecimal getPrice() {
+        return price;
+    }
+
+    public void setPrice(BigDecimal price) {
+        this.price = price;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    public Integer getTestType() {
+        return testType;
+    }
+
+    public void setTestType(Integer testType) {
+        this.testType = testType;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public void setDesc(String desc) {
+        this.desc = desc;
+    }
+
+    public Integer getVersion() {
+        return version;
+    }
+
+    public void setVersion(Integer version) {
+        this.version = version;
+    }
+
+    public Timestamp getLastUpdatedDt() {
+        return lastUpdatedDt;
+    }
+
+    public void setLastUpdatedDt(Timestamp lastUpdatedDt) {
+        this.lastUpdatedDt = lastUpdatedDt;
+    }
+
+    @Override
+    public String toString() {
+        return "H2UserMetaObj{" +
+                "id=" + id +
+                ", name='" + name + '\'' +
+                ", age=" + age +
+                ", price=" + price +
+                ", testType=" + testType +
+                ", desc='" + desc + '\'' +
+                ", version=" + version +
+                ", lastUpdatedDt=" + lastUpdatedDt +
+                '}';
+    }
+}

+ 14 - 5
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/mysql/MyMetaObjectHandler.java

@@ -15,6 +15,8 @@
  */
 package com.baomidou.mybatisplus.test.mysql;
 
+import java.sql.Timestamp;
+
 import org.apache.ibatis.reflection.MetaObject;
 
 import com.baomidou.mybatisplus.mapper.MetaObjectHandler;
@@ -38,16 +40,23 @@ public class MyMetaObjectHandler extends MetaObjectHandler {
 //			metaObject.setValue("name", "instert-fill");
 //		}
 
+        System.out.println("*************************");
+        System.out.println("insert fill");
+        System.out.println("*************************");
+
         // 测试下划线
-        Object testType = metaObject.getValue("testType");
-        System.err.println("testType==" + testType);
-        if (null == testType) {
-            metaObject.setValue("testType", 3);
+        Object testType = getFieldValByName("testType", metaObject);
+        System.out.println("testType="+testType);
+        if(testType==null){
+            setFieldValByName("testType", 3, metaObject);
         }
     }
 
     @Override
     public void updateFill(MetaObject metaObject) {
-
+        System.out.println("*************************");
+        System.out.println("update fill");
+        System.out.println("*************************");
+        setFieldValByName("lastUpdatedDt", new Timestamp(System.currentTimeMillis()), metaObject);
     }
 }

+ 13 - 0
mybatis-plus/src/test/resources/h2/spring-test-h2-metaobj.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns="http://www.springframework.org/schema/beans"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+    <context:component-scan base-package="com.baomidou.mybatisplus.test.h2"/>
+
+    <bean name="/DBConfig" class="com.baomidou.mybatisplus.test.h2.config.DBConfig" />
+    <bean name="/MybatisPlusMetaObjConfig" class="com.baomidou.mybatisplus.test.h2.config.MybatisPlusMetaObjConfig" />
+
+</beans>

+ 2 - 1
mybatis-plus/src/test/resources/h2/user.ddl.sql

@@ -1,5 +1,5 @@
 CREATE TABLE IF NOT EXISTS  h2user (
-	test_id BIGINT(20) NOT NULL ,
+	test_id BIGINT(20) NOT NULL AUTO_INCREMENT,
 	name VARCHAR(30) NULL DEFAULT NULL ,
 	age INT(11) NULL DEFAULT NULL ,
 	test_type INT(11) NULL ,
@@ -7,6 +7,7 @@ CREATE TABLE IF NOT EXISTS  h2user (
 	price DECIMAL(10,2) NULL DEFAULT NULL,
 	desc VARCHAR(30) NULL DEFAULT NULL ,
 	version INT(5) NULL DEFAULT NULL,
+	last_updated_dt TIMESTAMP NULL,
 	PRIMARY KEY (test_id)
 )