說十遍不如作一次 Better do it once than say it ten times.前端
最近開始負責一個數據量比較大的業務模塊,要求把相關數據所有查出來,不分頁,要組樹結構,數據從dao層到service由entity對象到Vo對象給前端展現。那麼就涉及到對象拷貝,開始的時候用的Spring的BeanUtils作對象轉換,並無什麼問題,後來到了測試那裏,加大數據量,發現接口愈來愈慢,開始覺得數據庫查詢問題,把sql搬到數據庫運行,發現並不慢,由於關鍵字段基本都走了索引,不會很慢,後來一步一步找,發現是BeanUtils耗時引發的,而後就有了下面的關於三種對象拷貝方式的實踐spring
這裏可能不少小夥伴只用過Spring的BeanUtils,其他的兩種沒用過,不過不要緊,接下來來個簡單的測試sql
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring的BeanUtils -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Apache的BeanUtils依賴 -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
</dependency>
<!-- mapstruct依賴 -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.2.0.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.2.0.Final</version>
</dependency>
</dependencies>
複製代碼
/**
* @description user 實體
* @author Wanm
* @date 2020/7/8 21:37
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String id;
private String name;
private Integer age;
private String address;
private String sex;
}
/**
* @description userVo
* @author Wanm
* @date 2020/7/8 21:37
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserVo {
private String id;
private String name;
private Integer age;
private String address;
private String sex;
}
/**
* @description UserTransfer
* @author Wanm
* @date 2020/7/8 21:37
*/
@Mapper
public interface UserTransfer {
/**
* entity轉vo
* @param user
* @return
*/
List<UserVo> entityToVo(List<User> user);
}
/**
* 測試類
*/
@SpringBootTest
class MapstructApplicationTests {
@Test
void contextLoads() {
//這裏拿100w數據作數據初始化
List<User> userList = new ArrayList<User>();
for (int i = 0; i < 1000000; i++) {
User user = new User(UUID.randomUUID().toString(),UUID.randomUUID().toString(),i,UUID.randomUUID().toString(),UUID.randomUUID().toString());
userList.add(user);
}
System.out.println(userList.get(0));
System.out.println("開始拷貝---------------------------------------");
testBeanUtils(userList);
testSpringBeanUtils(userList);
testMapStruct(userList);
}
/**
* Apache的BeanUtils
* @param userList
*/
public static void testBeanUtils(List<User> userList){
long start = System.currentTimeMillis();
List<UserVo> userVos = new ArrayList<>();
userList.forEach(item->{
UserVo userVo = new UserVo();
try {
BeanUtils.copyProperties(userVo,item);
userVos.add(userVo);
} catch (Exception e) {
e.printStackTrace();
}
});
long end = System.currentTimeMillis();
System.out.println(userVos.get(0));
System.out.println("集合大小參數驗證"+userVos.size()+"Apache的BeanUtils耗時:"+(end-start)+"ms");
}
/**
* Spring的BeanUtils
* @param userList
*/
public static void testSpringBeanUtils(List<User> userList){
long start = System.currentTimeMillis();
List<UserVo> userVos = new ArrayList<>();
userList.forEach(item->{
UserVo userVo = new UserVo();
try {
org.springframework.beans.BeanUtils.copyProperties(item,userVo);
userVos.add(userVo);
} catch (Exception e) {
e.printStackTrace();
}
});
long end = System.currentTimeMillis();
System.out.println(userVos.get(0));
System.out.println("集合大小參數驗證"+userVos.size()+"Spring的BeanUtils耗時:"+(end-start)+"ms");
}
/**
* mapStruct拷貝
* @param userList
*/
public void testMapStruct(List<User> userList){
long start = System.currentTimeMillis();
List<UserVo> userVos = Mappers.getMapper(UserTransfer.class).entityToVo(userList);
long end = System.currentTimeMillis();
System.out.println(userVos.get(0));
System.out.println("集合大小參數驗證"+userVos.size()+"mapStruct耗時:"+(end-start)+"ms");
}
}
複製代碼
Apache | Spring | MapStruct | |
---|---|---|---|
1000 | 67ms | 10ms | 2ms |
1w | 174ms | 35ms | 3ms |
10w | 808ms | 69ms | 9ms |
100w | 5620ms | 336ms | 42ms |
public class UserTransferImpl implements UserTransfer {
public UserTransferImpl() {
}
public List<UserVo> entityToVo(List<User> user) {
if (user == null) {
return null;
} else {
List<UserVo> list = new ArrayList(user.size());
Iterator var3 = user.iterator();
while(var3.hasNext()) {
User user1 = (User)var3.next();
list.add(this.userToUserVo(user1));
}
return list;
}
}
protected UserVo userToUserVo(User user) {
if (user == null) {
return null;
} else {
UserVo userVo = new UserVo();
userVo.setId(user.getId());
userVo.setName(user.getName());
userVo.setAge(user.getAge());
userVo.setAddress(user.getAddress());
userVo.setSex(user.getSex());
return userVo;
}
}
}
複製代碼
Ps:寫着寫着不知不覺零點了,不行了趕忙睡覺,狗命要緊,小夥伴們三連哦!!!