miemie 6 лет назад
Родитель
Сommit
d9900f71b2

+ 30 - 236
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/SerializationUtils.java

@@ -16,49 +16,16 @@
  */
 package com.baomidou.mybatisplus.core.toolkit;
 
-import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
-
 import java.io.*;
-import java.util.HashMap;
-import java.util.Map;
 
 
 /**
- * <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>
+ * <p>copy from org.springframework.util.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>
@@ -71,226 +38,53 @@ public class SerializationUtils {
      * @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
      */
+    @SuppressWarnings("unchecked")
     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 ExceptionUtils.mpe("ClassNotFoundException while reading cloned object data", ex);
-        } catch (final IOException ex) {
-            throw ExceptionUtils.mpe("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));
+        return (T) deserialize(objectData);
     }
 
-    // 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
+     * Serialize the given object to a byte array.
+     * @param object the object to serialize
+     * @return an array of bytes representing the object in a portable fashion
      */
-    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 ExceptionUtils.mpe(ex);
+    public static byte[] serialize(Object object) {
+        if (object == null) {
+            return null;
         }
-    }
-
-    /**
-     * <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 ExceptionUtils.mpe(ex);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+        try {
+            ObjectOutputStream oos = new ObjectOutputStream(baos);
+            oos.writeObject(object);
+            oos.flush();
+        } catch (IOException ex) {
+            throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
         }
+        return baos.toByteArray();
     }
 
     /**
-     * <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>
+     * Deserialize the byte array into an object.
      *
-     * @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
+     * @param bytes a serialized object
+     * @return the result of deserializing the bytes
      */
-    public static <T> T deserialize(final byte[] objectData) {
-        isTrue(objectData != null, "The byte[] must not be null");
-        return SerializationUtils.deserialize(new ByteArrayInputStream(objectData));
-    }
-
-    public static void isTrue(final boolean expression, final String message, final Object... values) {
-        if (!expression) {
-            throw new IllegalArgumentException(String.format(message, values));
-        }
-    }
-
-    /**
-     * <p>Custom specialization of the standard JDK {@link 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<?>> PRIMITIVE_TYPES =
-            new HashMap<>();
-
-        static {
-            PRIMITIVE_TYPES.put("byte", byte.class);
-            PRIMITIVE_TYPES.put("short", short.class);
-            PRIMITIVE_TYPES.put("int", int.class);
-            PRIMITIVE_TYPES.put("long", long.class);
-            PRIMITIVE_TYPES.put("float", float.class);
-            PRIMITIVE_TYPES.put("double", double.class);
-            PRIMITIVE_TYPES.put("boolean", boolean.class);
-            PRIMITIVE_TYPES.put("char", char.class);
-            PRIMITIVE_TYPES.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 ObjectInputStream
-         */
-        ClassLoaderAwareObjectInputStream(final InputStream in, final ClassLoader classLoader) throws IOException {
-            super(in);
-            this.classLoader = classLoader;
+    public static Object deserialize(byte[] bytes) {
+        if (bytes == null) {
+            return null;
         }
-
-        /**
-         * 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 = PRIMITIVE_TYPES.get(name);
-                    if (cls != null) {
-                        return cls;
-                    }
-                    throw cnfe;
-                }
-            }
+        try {
+            ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
+            return ois.readObject();
+        } catch (IOException ex) {
+            throw new IllegalArgumentException("Failed to deserialize object", ex);
+        } catch (ClassNotFoundException ex) {
+            throw new IllegalStateException("Failed to deserialize object type", ex);
         }
     }
 }

+ 15 - 17
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/Page.java

@@ -15,12 +15,12 @@
  */
 package com.baomidou.mybatisplus.extension.plugins.pagination;
 
-import java.util.Collections;
-import java.util.List;
-
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 
+import java.util.Collections;
+import java.util.List;
+
 /**
  * <p>
  * 简单分页模型
@@ -38,7 +38,7 @@ public class Page<T> implements IPage<T> {
      */
     private List<T> records = Collections.emptyList();
     /**
-     * 总数,当 total 为 null 或者大于 0 分页插件不在查询总数
+     * 总数,当 total 不为 0 时分页插件不会进行 count 查询
      */
     private long total = 0;
     /**
@@ -81,10 +81,10 @@ public class Page<T> implements IPage<T> {
      * @param size    每页显示条数
      */
     public Page(long current, long size) {
-        this(current, size, 0L);
+        this(current, size, 0);
     }
 
-    public Page(long current, long size, Long total) {
+    public Page(long current, long size, long total) {
         if (current > 1) {
             this.current = current;
         }
@@ -120,7 +120,7 @@ public class Page<T> implements IPage<T> {
     }
 
     @Override
-    public IPage<T> setRecords(List<T> records) {
+    public Page<T> setRecords(List<T> records) {
         this.records = records;
         return this;
     }
@@ -131,7 +131,7 @@ public class Page<T> implements IPage<T> {
     }
 
     @Override
-    public IPage<T> setTotal(long total) {
+    public Page<T> setTotal(long total) {
         this.total = total;
         return this;
     }
@@ -142,7 +142,7 @@ public class Page<T> implements IPage<T> {
     }
 
     @Override
-    public IPage<T> setSize(long size) {
+    public Page<T> setSize(long size) {
         this.size = size;
         return this;
     }
@@ -153,7 +153,7 @@ public class Page<T> implements IPage<T> {
     }
 
     @Override
-    public IPage<T> setCurrent(long current) {
+    public Page<T> setCurrent(long current) {
         this.current = current;
         return this;
     }
@@ -163,7 +163,7 @@ public class Page<T> implements IPage<T> {
         return ascs;
     }
 
-    public IPage<T> setAscs(List<String> ascs) {
+    public Page<T> setAscs(List<String> ascs) {
         if (CollectionUtils.isNotEmpty(ascs)) {
             this.ascs = ascs.toArray(new String[0]);
         }
@@ -177,9 +177,8 @@ public class Page<T> implements IPage<T> {
      * </p>
      *
      * @param ascs 多个升序字段
-     * @return
      */
-    public IPage<T> setAsc(String... ascs) {
+    public Page<T> setAsc(String... ascs) {
         this.ascs = ascs;
         return this;
     }
@@ -189,7 +188,7 @@ public class Page<T> implements IPage<T> {
         return descs;
     }
 
-    public IPage<T> setDescs(List<String> descs) {
+    public Page<T> setDescs(List<String> descs) {
         if (CollectionUtils.isNotEmpty(descs)) {
             this.descs = descs.toArray(new String[0]);
         }
@@ -202,9 +201,8 @@ public class Page<T> implements IPage<T> {
      * </p>
      *
      * @param descs 多个降序字段
-     * @return
      */
-    public IPage<T> setDesc(String... descs) {
+    public Page<T> setDesc(String... descs) {
         this.descs = descs;
         return this;
     }
@@ -214,7 +212,7 @@ public class Page<T> implements IPage<T> {
         return optimizeCountSql;
     }
 
-    public IPage<T> setOptimizeCountSql(boolean optimizeCountSql) {
+    public Page<T> setOptimizeCountSql(boolean optimizeCountSql) {
         this.optimizeCountSql = optimizeCountSql;
         return this;
     }

+ 12 - 4
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/SampleTest.java

@@ -1,15 +1,15 @@
 package com.baomidou.mybatisplus.test;
 
-import org.apache.ibatis.reflection.DefaultReflectorFactory;
-import org.apache.ibatis.reflection.MetaClass;
-import org.junit.Test;
-
 import com.baomidou.mybatisplus.core.conditions.Condition;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.toolkit.TableInfoHelper;
 import com.baomidou.mybatisplus.test.base.entity.CommonData;
 import com.baomidou.mybatisplus.test.base.entity.CommonLogicData;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.ibatis.reflection.DefaultReflectorFactory;
+import org.apache.ibatis.reflection.MetaClass;
+import org.junit.Test;
 
 public class SampleTest {
 
@@ -41,4 +41,12 @@ public class SampleTest {
         System.out.println(Condition.create().orderByAsc("1", "2", "3", "4").getSqlSegment());
         System.out.println(Condition.create().orderByDesc("1", "2", "3", "4").getSqlSegment());
     }
+
+    @Test
+    public void testClone() {
+        QueryWrapper<Object> wrapper = Condition.create().orderByAsc("1", "2", "3", "4");
+        QueryWrapper<Object> clone = ((QueryWrapper<Object>) wrapper.clone()).orderByDesc("5", "6", "7");
+        System.out.println(wrapper.getSqlSegment());
+        System.out.println(clone.getSqlSegment());
+    }
 }