Przeglądaj źródła

Merge branch 'dev' of https://gitee.com/baomidou/mybatis-plus into dev

willenfoo 7 lat temu
rodzic
commit
23bceea5b7

+ 7 - 2
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/test/EntityWrapperTest.java

@@ -64,8 +64,13 @@ public class EntityWrapperTest {
          * 实体带where ifneed
 		 */
         ew.setEntity(new User(1));
-        ew.where("name={0}", "'123'").addFilterIfNeed(false, "id=12");
-        String sqlSegment = ew.originalSql();
+        ew.where("name={0}", "'123'");
+        // 测试克隆
+        String sqlSegment = ew.clone().eq("a", 1).originalSql();
+        Assert.assertEquals("AND (name=? AND a = ?)", sqlSegment);
+        System.err.println("test11-clone = " + sqlSegment);
+        ew.addFilterIfNeed(false, "id=12");
+        sqlSegment = ew.originalSql();
         System.err.println("test11 = " + sqlSegment);
         Assert.assertEquals("AND (name=?)", sqlSegment);
     }

+ 5 - 0
mybatis-plus-generate/src/main/java/com/baomidou/mybatisplus/generator/config/rules/DbColumnType.java

@@ -26,7 +26,11 @@ package com.baomidou.mybatisplus.generator.config.rules;
 public enum DbColumnType {
     // 基本类型
     BASE_INT("int", null),
+    BASE_LONG("long", null),
+    BASE_CHAR("char", null),
+    BASE_BYTE("byte", null),
     BASE_BOOLEAN("boolean", null),
+    BASE_SHORT("short", null),
     BASE_FLOAT("float", null),
     BASE_DOUBLE("double", null),
 
@@ -37,6 +41,7 @@ public enum DbColumnType {
     FLOAT("Float", null),
     DOUBLE("Double", null),
     BOOLEAN("Boolean", null),
+    BYTE("Byte", null),
     BYTE_ARRAY("byte[]", null),
     CHARACTER("Character", null),
     OBJECT("Object", null),

+ 14 - 1
mybatis-plus-generate/src/main/java/com/baomidou/mybatisplus/generator/engine/AbstractTemplateEngine.java

@@ -278,7 +278,20 @@ public abstract class AbstractTemplateEngine {
      */
     protected boolean isCreate(String filePath) {
         File file = new File(filePath);
-        return !file.exists() || this.getConfigBuilder().getGlobalConfig().isFileOverride();
+        boolean exist = file.exists();
+        if (!exist) {
+            this.mkDir(file.getParentFile());
+        }
+        return !exist || this.getConfigBuilder().getGlobalConfig().isFileOverride();
+    }
+
+    protected void mkDir(File file) {
+        if (file.getParentFile().exists()) {
+            file.mkdir();
+        } else {
+            mkDir(file.getParentFile());
+            file.mkdir();
+        }
     }
 
 

+ 1 - 1
mybatis-plus-generate/src/test/java/com/baomidou/mybatisplus/test/generator/PostgreSQLGenerator.java

@@ -121,7 +121,7 @@ public class PostgreSQLGenerator extends GeneratorTest {
             @Override
             public String outputFile(TableInfo tableInfo) {
                 // 自定义输入文件名称
-                return "D://my_" + tableInfo.getEntityName() + ".java";
+                return "D://test/my_" + tableInfo.getEntityName() + ".java";
             }
         });
         cfg.setFileOutConfigList(focList);

+ 11 - 1
mybatis-plus-support/src/main/java/com/baomidou/mybatisplus/mapper/Wrapper.java

@@ -30,6 +30,7 @@ import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.toolkit.ArrayUtils;
 import com.baomidou.mybatisplus.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.toolkit.MapUtils;
+import com.baomidou.mybatisplus.toolkit.SerializationUtils;
 import com.baomidou.mybatisplus.toolkit.SqlUtils;
 import com.baomidou.mybatisplus.toolkit.StringUtils;
 
@@ -1475,7 +1476,7 @@ public abstract class Wrapper<T> implements Serializable {
             for (int i = 0; i < params.length; ++i) {
                 String genParamName = MP_GENERAL_PARAMNAME + paramNameSeq.incrementAndGet();
                 sqlStr = sqlStr.replace(String.format(PLACE_HOLDER, i),
-                        String.format(MYBATIS_PLUS_TOKEN, getParamAlias(), genParamName));
+                    String.format(MYBATIS_PLUS_TOKEN, getParamAlias(), genParamName));
                 paramNameValuePairs.put(genParamName, params[i]);
             }
         }
@@ -1540,4 +1541,13 @@ public abstract class Wrapper<T> implements Serializable {
         this.paramAlias = paramAlias;
         return this;
     }
+
+    /**
+     * <p>
+     * 克隆本身 fixed github issues/241
+     * </p>
+     */
+    public Wrapper<T> clone() {
+        return SerializationUtils.clone(this);
+    }
 }

+ 288 - 0
mybatis-plus-support/src/main/java/com/baomidou/mybatisplus/toolkit/SerializationUtils.java

@@ -0,0 +1,288 @@
+package com.baomidou.mybatisplus.toolkit;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+
+/**
+ * <p>Assists with the serialization process and performs additional functionality based
+ * on serialization.</p>
+ * <p>
+ * <ul>
+ * <li>Deep clone using serialization
+ * <li>Serialize managing finally and IOException
+ * <li>Deserialize managing finally and IOException
+ * </ul>
+ * <p>
+ * <p>This class throws exceptions for invalid {@code null} inputs.
+ * Each method documents its behaviour in more detail.</p>
+ * <p>
+ * <p>#ThreadSafe#</p>
+ * <p>copy from org.apache.commons.lang3.SerializationUtils</p>
+ *
+ * @since 1.0
+ */
+public class SerializationUtils {
+
+    /**
+     * <p>SerializationUtils instances should NOT be constructed in standard programming.
+     * Instead, the class should be used as {@code SerializationUtils.clone(object)}.</p>
+     * <p>
+     * <p>This constructor is public to permit tools that require a JavaBean instance
+     * to operate.</p>
+     *
+     * @since 2.0
+     */
+    public SerializationUtils() {
+        super();
+    }
+
+    // Clone
+    //-----------------------------------------------------------------------
+
+    /**
+     * <p>Deep clone an {@code Object} using serialization.</p>
+     * <p>
+     * <p>This is many times slower than writing clone methods by hand
+     * on all objects in your object graph. However, for complex object
+     * graphs, or for those that don't support deep cloning this can
+     * be a simple alternative implementation. Of course all the objects
+     * must be {@code Serializable}.</p>
+     *
+     * @param <T>    the type of the object involved
+     * @param object the {@code Serializable} object to clone
+     * @return the cloned object
+     * @throws MybatisPlusException (runtime) if the serialization fails
+     */
+    public static <T extends Serializable> T clone(final T object) {
+        if (object == null) {
+            return null;
+        }
+        final byte[] objectData = serialize(object);
+        final ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
+
+        try (ClassLoaderAwareObjectInputStream in = new ClassLoaderAwareObjectInputStream(bais,
+            object.getClass().getClassLoader())) {
+            /*
+             * when we serialize and deserialize an object,
+             * it is reasonable to assume the deserialized object
+             * is of the same type as the original serialized object
+             */
+            @SuppressWarnings("unchecked") // see above
+            final T readObject = (T) in.readObject();
+            return readObject;
+
+        } catch (final ClassNotFoundException ex) {
+            throw new MybatisPlusException("ClassNotFoundException while reading cloned object data", ex);
+        } catch (final IOException ex) {
+            throw new MybatisPlusException("IOException while reading or closing cloned object data", ex);
+        }
+    }
+
+    /**
+     * Performs a serialization roundtrip. Serializes and deserializes the given object, great for testing objects that
+     * implement {@link Serializable}.
+     *
+     * @param <T> the type of the object involved
+     * @param msg the object to roundtrip
+     * @return the serialized and deserialized object
+     * @since 3.3
+     */
+    @SuppressWarnings("unchecked") // OK, because we serialized a type `T`
+    public static <T extends Serializable> T roundtrip(final T msg) {
+        return (T) SerializationUtils.deserialize(SerializationUtils.serialize(msg));
+    }
+
+    // Serialize
+    //-----------------------------------------------------------------------
+
+    /**
+     * <p>Serializes an {@code Object} to the specified stream.</p>
+     * <p>
+     * <p>The stream will be closed once the object is written.
+     * This avoids the need for a finally clause, and maybe also exception
+     * handling, in the application code.</p>
+     * <p>
+     * <p>The stream passed in is not buffered internally within this method.
+     * This is the responsibility of your application if desired.</p>
+     *
+     * @param obj          the object to serialize to bytes, may be null
+     * @param outputStream the stream to write to, must not be null
+     * @throws IllegalArgumentException if {@code outputStream} is {@code null}
+     * @throws MybatisPlusException     (runtime) if the serialization fails
+     */
+    public static void serialize(final Serializable obj, final OutputStream outputStream) {
+        isTrue(outputStream != null, "The OutputStream must not be null");
+        try (ObjectOutputStream out = new ObjectOutputStream(outputStream)) {
+            out.writeObject(obj);
+        } catch (final IOException ex) {
+            throw new MybatisPlusException(ex);
+        }
+    }
+
+    /**
+     * <p>Serializes an {@code Object} to a byte array for
+     * storage/serialization.</p>
+     *
+     * @param obj the object to serialize to bytes
+     * @return a byte[] with the converted Serializable
+     * @throws MybatisPlusException (runtime) if the serialization fails
+     */
+    public static byte[] serialize(final Serializable obj) {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
+        serialize(obj, baos);
+        return baos.toByteArray();
+    }
+
+    // Deserialize
+    //-----------------------------------------------------------------------
+
+    /**
+     * <p>
+     * Deserializes an {@code Object} from the specified stream.
+     * </p>
+     * <p>
+     * <p>
+     * The stream will be closed once the object is written. This avoids the need for a finally clause, and maybe also
+     * exception handling, in the application code.
+     * </p>
+     * <p>
+     * <p>
+     * The stream passed in is not buffered internally within this method. This is the responsibility of your
+     * application if desired.
+     * </p>
+     * <p>
+     * <p>
+     * If the call site incorrectly types the return value, a {@link ClassCastException} is thrown from the call site.
+     * Without Generics in this declaration, the call site must type cast and can cause the same ClassCastException.
+     * Note that in both cases, the ClassCastException is in the call site, not in this method.
+     * </p>
+     *
+     * @param <T>         the object type to be deserialized
+     * @param inputStream the serialized object input stream, must not be null
+     * @return the deserialized object
+     * @throws IllegalArgumentException if {@code inputStream} is {@code null}
+     * @throws MybatisPlusException     (runtime) if the serialization fails
+     */
+    public static <T> T deserialize(final InputStream inputStream) {
+        isTrue(inputStream != null, "The InputStream must not be null");
+        try (ObjectInputStream in = new ObjectInputStream(inputStream)) {
+            @SuppressWarnings("unchecked") final T obj = (T) in.readObject();
+            return obj;
+        } catch (final ClassNotFoundException | IOException ex) {
+            throw new MybatisPlusException(ex);
+        }
+    }
+
+    /**
+     * <p>
+     * Deserializes a single {@code Object} from an array of bytes.
+     * </p>
+     * <p>
+     * <p>
+     * If the call site incorrectly types the return value, a {@link ClassCastException} is thrown from the call site.
+     * Without Generics in this declaration, the call site must type cast and can cause the same ClassCastException.
+     * Note that in both cases, the ClassCastException is in the call site, not in this method.
+     * </p>
+     *
+     * @param <T>        the object type to be deserialized
+     * @param objectData the serialized object, must not be null
+     * @return the deserialized object
+     * @throws IllegalArgumentException if {@code objectData} is {@code null}
+     * @throws MybatisPlusException     (runtime) if the serialization fails
+     */
+    public static <T> T deserialize(final byte[] objectData) {
+        isTrue(objectData != null, "The byte[] must not be null");
+        return SerializationUtils.deserialize(new ByteArrayInputStream(objectData));
+    }
+
+    /**
+     * <p>Custom specialization of the standard JDK {@link java.io.ObjectInputStream}
+     * that uses a custom  <code>ClassLoader</code> to resolve a class.
+     * If the specified <code>ClassLoader</code> is not able to resolve the class,
+     * the context classloader of the current thread will be used.
+     * This way, the standard deserialization work also in web-application
+     * containers and application servers, no matter in which of the
+     * <code>ClassLoader</code> the particular class that encapsulates
+     * serialization/deserialization lives. </p>
+     * <p>
+     * <p>For more in-depth information about the problem for which this
+     * class here is a workaround, see the JIRA issue LANG-626. </p>
+     */
+    static class ClassLoaderAwareObjectInputStream extends ObjectInputStream {
+
+        private static final Map<String, Class<?>> primitiveTypes =
+            new HashMap<>();
+
+        static {
+            primitiveTypes.put("byte", byte.class);
+            primitiveTypes.put("short", short.class);
+            primitiveTypes.put("int", int.class);
+            primitiveTypes.put("long", long.class);
+            primitiveTypes.put("float", float.class);
+            primitiveTypes.put("double", double.class);
+            primitiveTypes.put("boolean", boolean.class);
+            primitiveTypes.put("char", char.class);
+            primitiveTypes.put("void", void.class);
+        }
+
+        private final ClassLoader classLoader;
+
+        /**
+         * Constructor.
+         *
+         * @param in          The <code>InputStream</code>.
+         * @param classLoader classloader to use
+         * @throws IOException if an I/O error occurs while reading stream header.
+         * @see java.io.ObjectInputStream
+         */
+        ClassLoaderAwareObjectInputStream(final InputStream in, final ClassLoader classLoader) throws IOException {
+            super(in);
+            this.classLoader = classLoader;
+        }
+
+        /**
+         * Overridden version that uses the parameterized <code>ClassLoader</code> or the <code>ClassLoader</code>
+         * of the current <code>Thread</code> to resolve the class.
+         *
+         * @param desc An instance of class <code>ObjectStreamClass</code>.
+         * @return A <code>Class</code> object corresponding to <code>desc</code>.
+         * @throws IOException            Any of the usual Input/Output exceptions.
+         * @throws ClassNotFoundException If class of a serialized object cannot be found.
+         */
+        @Override
+        protected Class<?> resolveClass(final ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+            final String name = desc.getName();
+            try {
+                return Class.forName(name, false, classLoader);
+            } catch (final ClassNotFoundException ex) {
+                try {
+                    return Class.forName(name, false, Thread.currentThread().getContextClassLoader());
+                } catch (final ClassNotFoundException cnfe) {
+                    final Class<?> cls = primitiveTypes.get(name);
+                    if (cls != null) {
+                        return cls;
+                    }
+                    throw cnfe;
+                }
+            }
+        }
+
+    }
+
+    public static void isTrue(final boolean expression, final String message, final Object... values) {
+        if (!expression) {
+            throw new IllegalArgumentException(String.format(message, values));
+        }
+    }
+}