版权声明:这可是本菇凉辛辛苦苦原创的,转载请一定带上我家地址,不要忘记了哈 . https://blog.csdn.net/u011314442/article/details/90140532
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import tk.mybatis.mapper.entity.Example; import com.github.pagehelper.PageHelper; ... @Override public List<RepaymentPlan> listRepaymentPlan(Integer start) { Example example = new Example(RepaymentPlan.class); // 排序 example.orderBy("id"); // 条件查询 example.createCriteria() .andNotEqualTo("repayStatus", 3) .andLessThanOrEqualTo("shouldRepayDate", new Date()); // 分页 PageHelper.startPage(start, 20); // 每次查询20条 return repaymentPlanMapper.selectByExample(example); } |
2. PageHelper 使用详解见文章:分页插件pageHelpler的使用(ssm框架中)服务器端分页 3. 更多关于 Example 的使用说明见文章: java 查询功能实现的八种方式 MyBatis : Mapper 接口以及 Example 使用实例、详解 4. 当只是查询数据,不需要返回总条数时可选择此方法:
|
1 |
PageHelper.startPage(第几页, 20,false); // 每次查询20条 |
当数据量极大时,可以快速查询,忽略总条数的查询,减少查询时间。 以下是该方法原码实现: ————————————————- 2019.5.13 后记 : 1)分页的写法 下图中黄框中的写法运行 比红框中 快,不知道是不是插件本身也会有费时: 2)再补充一种分页方式,mybatis 自带的 RowBounds:
|
1 2 3 4 5 6 7 8 9 10 |
public List<RepayPlan> listRepayPlan(int start) { // 查询所有未还款结清且应还日期小于当前时间的账单 Example example = new Example(RepayPlan.class); example.orderBy("id "); // 按id排序 example.createCriteria() .andNotEqualTo("repayStatus", 3) .andLessThanOrEqualTo("shouldRepayDate", new Date()); RowBounds rowBounds = new RowBounds(start, 20); // 每次查询20条 return epaymentPlanMapper.selectByExampleAndRowBounds(example,rowBounds); } |
推荐用 RowBounds :mybatis 自带的,且速度快 。个人运行,后 2 种分页明显比 PageHelper 快。 from:https://cloud.tencent.com/developer/article/1433161
View Details在开发过程中遇到一个问题,服务器经过排序返回后的字符串数据使用fastjson解析后,数据顺序发生变化,引起业务异常。 解决办法: 1、解析时增加参数不调整顺序 JSONObject respondeBodyJson = JSONObject.parseObject(jsonStr, Feature.OrderedField); 2、初始化json对象为有序对象: JSONObject retObj = new JSONObject(true); 这样生成的json对象就与放入数据时一致。 3、使用Gson解析 JsonObject returnData = new JsonParser().parse(replyString).getAsJsonObject(); ———————————————— 版权声明:本文为CSDN博主「long2010110」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/long2010110/article/details/81537820
View Details场景 两个不同的类,其中一部分的属性相同。 要把其中一个对象的一些属性赋值给另一个对象。 最原始的方式是依次调用两个对象的set和get方法,挨个赋值。 但是spring提供了BanUtils的方法copyPrpperties可以实现。 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书、教程推送与免费下载。 实现 引入包
|
1 |
import org.springframework.beans.BeanUtils; |
然后调用
|
1 |
BeanUtils.copyProperties(kqDkszJl,kqDksz); |
其中左边是要取值的对象,右边是要赋值的对象。 博客园: https://www.cnblogs.com/badaoliumangqizhi/ 关注公众号 霸道的程序猿 获取编程相关电子书、教程推送与免费下载。 from:https://www.cnblogs.com/badaoliumangqizhi/p/13786384.html
View Details转换字符串示例:
|
1 2 |
String array2 = "{'i':'2','b':'3'}"; JSONObject parseObject = JSON.parseObject(array2); |
结果:
|
1 |
{"b":"3","i":"2"} |
我们会发现顺序与原来的字符串顺序不一致。 通过DEBUG去com.alibaba.fastjson.parser.DefaultJSONParser的下述方法
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
public Object parse(Object fieldName) { final JSONLexer lexer = this.lexer; switch (lexer.token()) { case SET: lexer.nextToken(); HashSet<Object> set = new HashSet<Object>(); parseArray(set, fieldName); return set; case TREE_SET: lexer.nextToken(); TreeSet<Object> treeSet = new TreeSet<Object>(); parseArray(treeSet, fieldName); return treeSet; case LBRACKET: JSONArray array = new JSONArray(); parseArray(array, fieldName); if (lexer.isEnabled(Feature.UseObjectArray)) { return array.toArray(); } return array; case LBRACE: //重点就是此行的lexer.isEnabled(Feature.OrderedField)=false JSONObject object = new JSONObject(lexer.isEnabled(Feature.OrderedField)); return parseObject(object, fieldName); // case LBRACE: { // Map<String, Object> map = lexer.isEnabled(Feature.OrderedField) // ? new LinkedHashMap<String, Object>() // : new HashMap<String, Object>(); // Object obj = parseObject(map, fieldName); // if (obj != map) { // return obj; // } // return new JSONObject(map); // } case LITERAL_INT: Number intValue = lexer.integerValue(); lexer.nextToken(); return intValue; case LITERAL_FLOAT: Object value = lexer.decimalValue(lexer.isEnabled(Feature.UseBigDecimal)); lexer.nextToken(); return value; |
重点就是此行的lexer.isEnabled(Feature.OrderedField)=false,打开JSONObject的源码构造方法可以发现当ordered参数值为false时使用的是HashMap存放数据。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public JSONObject(int initialCapacity, boolean ordered){ if (ordered) { map = new LinkedHashMap<String, Object>(initialCapacity); } else { map = new HashMap<String, Object>(initialCapacity); } } |
hashmap是数组加链表结构,根据key的hash算法确定在数组中的位置,当发生hash冲突的时候,根据二叉树或者红黑树构成链表。所以是有序的,key确定,位置也就确定了。 如果要实现转换前的数据顺序与转换后的数据顺序一致,可以使用如下方式:
|
1 2 3 |
String array2 = "{'i':'2','b':'3'}"; JSONObject parseObject = JSON.parseObject(array2, Feature.OrderedField); |
此时会使用LinkedHashMap,LinkedHashMap的内部维持了一个双向链表,保存了数据的插入顺序,遍历时,先得到的数据便是先插入的。 from:https://blog.csdn.net/h363659487/article/details/103880710
View Detailsspring-boot继承mybatis启动时,警告如下: 2018-09-10 15:00:14.721 WARN tk.mybatis.spring.mapper.ClassPathMapperScanner --No MyBatis mapper was found in '[com.kevin]' package. Please check your configuration. 使用的tk的开源项目进行mybatis集成,百度了很多解决方案,最终看到一位前辈介绍:doScan()会扫描启动类同级目录下的mapper接口,但是合理的目录结果绝对不允许所有的mapper都在启动类目录下,所以在启动类目录下添加了一个伪mapper,如下: 再重新启动服务,就不会出现如上warn信息了…… from:https://my.oschina.net/kevin2kelly/blog/2046324 ========================================================================================= 光子:通过以上兄弟的方法,我的警告确实没有了。但经过dev-tools热启动后还是会提醒: 无法获取实体类com.w3cnet.doctoradvice.entity.HisvMzbrJzxx对应的表名 …… 还需要安装一下:Mapper Spring Boot Starter ,贴上地址:
|
1 2 |
// https://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter compile group: 'tk.mybatis', name: 'mapper-spring-boot-starter', version: '2.1.5' |
折腾了几次,终于完美解决…… 参考:https://blog.csdn.net/zwrlj527/article/details/91824220
View Details内容简介 本文主要说明在Java8及以上版本中,使用stream().filter()来过滤一个List对象,查找符合条件的对象集合。 List对象类(StudentInfo)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
public class StudentInfo implements Comparable<StudentInfo> { //名称 private String name; //性别 true男 false女 private Boolean gender; //年龄 private Integer age; //身高 private Double height; //出生日期 private LocalDate birthday; public StudentInfo(String name, Boolean gender, Integer age, Double height, LocalDate birthday){ this.name = name; this.gender = gender; this.age = age; this.height = height; this.birthday = birthday; } public String toString(){ String info = String.format("%s\t\t%s\t\t%s\t\t\t%s\t\t%s",this.name,this.gender.toString(),this.age.toString(),this.height.toString(),birthday.toString()); return info; } public static void printStudents(List<StudentInfo> studentInfos){ System.out.println("[姓名]\t\t[性别]\t\t[年龄]\t\t[身高]\t\t[生日]"); System.out.println("----------------------------------------------------------"); studentInfos.forEach(s->System.out.println(s.toString())); System.out.println(" "); } @Override public int compareTo(StudentInfo ob) { return this.age.compareTo(ob.getAge()); //return 1; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Boolean getGender() { return gender; } public void setGender(Boolean gender) { this.gender = gender; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Double getHeight() { return height; } public void setHeight(Double height) { this.height = height; } public LocalDate getBirthday() { return birthday; } public void setBirthday(LocalDate birthday) { this.birthday = birthday; } } |
测试数据
|
1 2 3 4 5 6 |
//测试数据,请不要纠结数据的严谨性 List<StudentInfo> studentList = new ArrayList<>(); studentList.add(new StudentInfo("李小明",true,18,1.76,LocalDate.of(2001,3,23))); studentList.add(new StudentInfo("张小丽",false,18,1.61,LocalDate.of(2001,6,3))); studentList.add(new StudentInfo("王大朋",true,19,1.82,LocalDate.of(2000,3,11))); studentList.add(new StudentInfo("陈小跑",false,17,1.67,LocalDate.of(2002,10,18))); |
输出Students列表
|
1 2 |
//输出List StudentInfo.printStudents(studentList); |
输出结果如下图: 使用filter()过滤List
|
1 2 3 4 |
//查找身高在1.8米及以上的男生 List<StudentInfo> boys = studentList.stream().filter(s->s.getGender() && s.getHeight() >= 1.8).collect(Collectors.toList()); //输出查找结果 StudentInfo.printStudents(boys); |
结果如下图: from:https://www.cnblogs.com/codecat/p/10912454.html
View DetailsAPI: https://www.runoob.com/java/java8-streams.html
|
1 2 3 4 |
mylist.stream() .map(myfunction->{ return item; }).collect(Collectors.toList()); |
说明: steam():把一个源数据,可以是集合,数组,I/O channel, 产生器generator 等,转化成流。 forEach():迭代流中的每个数据。以下代码片段使用 forEach 输出了10个随机数.
|
1 2 |
Random random = new Random(); random.ints().limit(10).forEach(System.out::println); |
map():用于映射每个元素到对应的结果。以下代码片段使用 map 输出了元素对应的平方数:
|
1 2 3 |
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); // 获取对应的平方数 List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList()); |
filter():filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:
|
1 2 3 4 5 6 7 8 |
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 获取空字符串的数量 int count = strings.stream().filter(string -> string.isEmpty()).count(); limit limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 10 条数据: Random random = new Random(); random.ints().limit(10).forEach(System.out::println); |
sorted(): 用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
|
1 2 3 4 5 6 7 8 9 |
Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println); 并行(parallel)程序 parallelStream 是流并行处理程序的代替方法。以下实例我们使用 parallelStream 来输出空字符串的数量: List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 获取空字符串的数量 int count = strings.parallelStream().filter(string -> string.isEmpty()).count(); 我们可以很容易的在顺序运行和并行直接切换。 |
Collectors(): 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
|
1 2 3 4 5 6 |
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("筛选列表: " + filtered); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("合并字符串: " + mergedString); |
from:https://blog.csdn.net/shine_guo_star/article/details/94383319
View Details转: https://blog.csdn.net/sanchan/article/details/70753645 java8的optional的使用: http://www.jdon.com/idea/java/using-optional-effectively-in-java-8.html http://www.runoob.com/java/java8-optional-class.html Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。 Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。 Optional 类的引入很好的解决空指针异常。 类声明 以下是一个 java.util.Optional<T> 类的声明: public final class Optional<T> extends Object
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
在Java 8中stream().map(),您可以将对象转换为其他对象。查看以下示例: 1.大写字符串列表 1.1简单的Java示例将Strings列表转换为大写。 TestJava8.java package com.mkyong.java8; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class TestJava8 { public static void main(String[] args) { List<String> alpha = Arrays.asList("a", "b", "c", "d"); //Before Java8 List<String> alphaUpper = new ArrayList<>(); for (String s : alpha) { alphaUpper.add(s.toUpperCase()); } System.out.println(alpha); //[a, b, c, d] System.out.println(alphaUpper); //[A, B, C, D] // Java 8 List<String> collect = alpha.stream().map(String::toUpperCase).collect(Collectors.toList()); System.out.println(collect); //[A, B, C, D] // Extra, streams apply to any data type. List<Integer> num = Arrays.asList(1,2,3,4,5); List<Integer> collect1 = num.stream().map(n -> n * 2).collect(Collectors.toList()); System.out.println(collect1); //[2, 4, 6, 8, 10] } } 2.对象列表 - >字符串列表 2.1 name从staff对象列表中获取所有值。 Staff.java package com.mkyong.java8; import java.math.BigDecimal; public class Staff { private String name; private int age; private BigDecimal salary; //... } TestJava8.java package com.mkyong.java8; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class TestJava8 { public static void main(String[] args) { List<Staff> staff = Arrays.asList( new Staff("mkyong", 30, new BigDecimal(10000)), new Staff("jack", 27, new BigDecimal(20000)), new Staff("lawrence", 33, new BigDecimal(30000)) ); //Before Java 8 List<String> result = new ArrayList<>(); for (Staff x : staff) { result.add(x.getName()); } System.out.println(result); //[mkyong, jack, lawrence] //Java 8 List<String> collect = staff.stream().map(x -> x.getName()).collect(Collectors.toList()); System.out.println(collect); //[mkyong, jack, lawrence] } } 对象列表 - >其他对象列表 3.1此示例说明如何将staff对象列表转换为对象列表StaffPublic。 Staff.java package com.mkyong.java8; import java.math.BigDecimal; public class Staff { private String name; private int age; private BigDecimal salary; //... } StaffPublic.java package com.mkyong.java8; public class StaffPublic { private String name; private int age; private String extra; //... } 3.2 Java 8之前。 BeforeJava8.java package com.mkyong.java8; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class BeforeJava8 { public static void main(String[] args) { List<Staff> staff = Arrays.asList( new Staff("mkyong", 30, new BigDecimal(10000)), new Staff("jack", 27, new BigDecimal(20000)), new Staff("lawrence", 33, new BigDecimal(30000)) ); List<StaffPublic> result = convertToStaffPublic(staff); System.out.println(result); } private static List<StaffPublic> convertToStaffPublic(List<Staff> staff) { List<StaffPublic> result = new ArrayList<>(); for (Staff temp : staff) { StaffPublic obj = new StaffPublic(); obj.setName(temp.getName()); obj.setAge(temp.getAge()); if ("mkyong".equals(temp.getName())) { obj.setExtra("this field is for mkyong only!"); } result.add(obj); } return result; } } 输出 [ StaffPublic{name='mkyong', age=30, extra='this field is for mkyong only!'}, StaffPublic{name='jack', age=27, extra='null'}, StaffPublic{name='lawrence', age=33, extra='null'} ] 1 2 3 4 5 3.3 Java 8的例子。 NowJava8.java package com.mkyong.java8; package com.hostingcompass.web.java8; import java.math.BigDecimal; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class NowJava8 { public static void main(String[] args) { List<Staff> staff = Arrays.asList( new Staff("mkyong", 30, new BigDecimal(10000)), new Staff("jack", 27, new BigDecimal(20000)), new Staff("lawrence", 33, new BigDecimal(30000)) ); // convert inside the map() method directly. List<StaffPublic> result = staff.stream().map(temp -> { StaffPublic obj = new StaffPublic(); obj.setName(temp.getName()); obj.setAge(temp.getAge()); if ("mkyong".equals(temp.getName())) { obj.setExtra("this field is for mkyong only!"); } return obj; }).collect(Collectors.toList()); System.out.println(result); } } [ StaffPublic{name='mkyong', age=30, extra='this field is for mkyong only!'}, StaffPublic{name='jack', age=27, extra='null'}, StaffPublic{name='lawrence', age=33, extra='null'} ] |
from:https://www.cnblogs.com/fengli9998/p/9002377.html
View Details使用IDEA创建gradle项目后,执行main方法时会自动运行gradle的一些build task,导致启动很慢,如下图: 解决方法: 打开设置页面,进行如下修改: from:https://zhoujun.blog.csdn.net/article/details/103372893
View Details一般情况下,DO是用来映射数据库记录的实体类,DTO是用来在网络上传输的实体类。两者的不同除了适用场景不同外还有就是DTO需要实现序列化接口。从DB查询到数据之后,ORM框架会把数据转换成DO对象,通常我们需要再把DO对象转换为DTO对象。同样的,插入数据到DB之前需要将DTO对象转换为DO对象然后交给ORM框架去执行JDBC。 通常用到的转换工具类BeanUtils是通过反射来实现的,实现源码如下
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
public static <T> T convertObject(Object sourceObj, Class<T> targetClz) { if (sourceObj == null) { return null; } if (targetClz == null) { throw new IllegalArgumentException("parameter clz shoud not be null"); } try { Object targetObj = targetClz.newInstance(); BeanUtils.copyProperties(sourceObj, targetObj); return (T) targetObj; } catch (Exception e) { throw new RuntimeException(e); } } private static void copyProperties(Object source, Object target, Class<?> editable, String[] ignoreProperties) throws BeansException { Assert.notNull(source, "Source must not be null"); Assert.notNull(target, "Target must not be null"); Class<?> actualEditable = target.getClass(); if (editable != null) { if (!editable.isInstance(target)) { throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]"); } actualEditable = editable; } PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable); List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null; for (PropertyDescriptor targetPd : targetPds) { if (targetPd.getWriteMethod() != null && (ignoreProperties == null || (!ignoreList.contains(targetPd.getName())))) { PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName()); if (sourcePd != null && sourcePd.getReadMethod() != null) { try { Method readMethod = sourcePd.getReadMethod(); if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { readMethod.setAccessible(true); } Object value = readMethod.invoke(source); Method writeMethod = targetPd.getWriteMethod(); if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { writeMethod.setAccessible(true); } writeMethod.invoke(target, value); } catch (Throwable ex) { throw new FatalBeanException("Could not copy properties from source to target", ex); } } } } } |
也可以通过mapstruct来实现,这种方式是在Mapper接口的包中生成一个对应mapper的实现类,实现类的源码如下。显然这种方式的实现更为普通,看起来没有BeanUtils的实现那么复杂。不过BeanUtils通过反射实现更为通用,可以为各种类型的DTO实现转换。而mapstruct只是帮我们生产了我们不想写的代码。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
public Task doToDTO(TaskDO taskDO) { if (taskDO == null) { return null; } else { Task task = new Task(); task.setId(taskDO.getId()); //其他字段的set task.setGmtCreate(taskDO.getGmtCreate()); task.setGmtModified(taskDO.getGmtModified()); return task; } } |
对比以上两种方式,显然使用BeanUtils来进行转换时需要写的代码更少,内部的通过反射便可以进行get/set操作。而mapstruct实现上需要写的代码稍微多一点,但是这种方式的性能比通过反射实现更好。下面写一段代码来测试两种方式实现的性能差别。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public void testConvert() { System.out.println("####testConvert"); int num = 100000; TaskDO taskDO = new TaskDO(); long start = System.currentTimeMillis(); for (int i = 0; i < num; i ++) { Task task = ObjectConvertor.convertObject(taskDO, Task.class); } System.out.println(System.currentTimeMillis() - start); //--------------------------------------------- start = System.currentTimeMillis(); for (int i = 0; i < num; i ++) { Task task = taskMapper.doToDTO(taskDO); } System.out.println(System.currentTimeMillis() - start); } |
以上测试代码中分别使用两种方式对同一个DO对象进行n次转换,两次转换的耗时统计如下。单位:ms 次数 1 10 100 1000 10000 100000 1000000 10000000 Mapstruct 0 1 1 1 2 4 8 8 BeanUtil 9 7 11 26 114 500 1469 14586 可见当转换数量级增加时,使用BeanUtil的耗时急剧上升,而使用Mapstruct的耗时则保持在比较低的水平。 在一个系统中,ORM对DB的各种操作几乎都会涉及到DO和DTO之间的转换,参考以上表格的统计结果,更推荐使用Mapstruct。 from:https://www.cnblogs.com/umgsai/p/8570652.html
View Details