Java中DO,VO,DTO结构一样,但在意义上或者说功能上不一样,DO定义实体,VO定义视图层数据返回,DTO用于查询实体参数,通常进行转化可以自写setter/getter方法或者使用BeanUtils的属性复制方法(运行期利用反射),具体原理可以查看源码或者百度。MapStruct是同学推荐的一个开源工具,是在编译期生成对应的实体类来完成属性复制,使用方便,这里做个简单的笔记,方便以后使用。
1、添加jar包,maven项目直接添加依赖
1.1.0.Final
org.mapstruct
mapstruct-jdk8
${map-struct-version}
org.mapstruct
mapstruct-processor
${map-struct-version}
2、定义映射接口(也可以是抽象类)
package com.fc.mapper;
import com.fc.bean.Person;
import com.fc.bean.User;
import com.fc.bean.query.UserDTO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
/**
* spring模式相当于@Component注解,注册bean到spring容器
*/
@Mapper(componentModel = "spring")
public interface UserMapper {
/**
* 默认模式下实例获取,编译后会生成实现类
*/
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
/**
* 实体转换,字段名相同可省略@Mappings
*
* @param user
* @return
*/
UserDTO userToUserDTO(User user);
/**
* 同上注释
*
* @param userDTO
* @return
*/
User userDTO2User(UserDTO userDTO);
@Mappings({
@Mapping(source = "id", target = "personId"),
@Mapping(source = "sex", target = "gender")
})
Person userToPerson(User user);
}
* @Mapper的componentModel有多个取值,默认是default,可以省略,这时需要定义实例的获取方式(见INSTANCE);spring取值是在spring环境中注册bean到容器,此时可以省略INSTANCE的初始化并且要注意spring容器启动时要能加载到该类,使用时可以@Autowired方式注入。
* 实际应用default和spring方式不会同时出现,不过这里的示例这样写也是可以的并且都可以正常执行
* 接下来是定义实体转换方法:
(1)属性名称均相同,则可以直接定义userToUserDTO方法所示,无需添加@Mappings注解来映射属性
(2)部分属性名称相同,则可以定义如userToPerson所示,使用@Mappings注解来映射属性,具体参考@Mapping注解,source是参数类的属性,target是要转换的类的属性,此外@Mapping还支持格式处理如String numberFormat() default "";以及Java表达式String expression() default "";可自行去了解更多使用情况
3、进行转换测试(default模型需先自行编译)
public class UserMapperTest{
private User user;
@Before
public void init() {
user = new User();
user.setId(111L);
user.setAge(26);
user.setCreateTime(Calendar.getInstance().getTime());
user.setLoginName("ceChi");
user.setLoginPassword("123456");
user.setRealName("cece");
user.setRole("admin");
user.setSex('F');
user.setUpdateTime(Calendar.getInstance().getTime());
}
@Test
public void testUserToUserDTO() {
UserDTO userDTO = UserMapper.INSTANCE.userToUserDTO(user);
System.out.println(userDTO);
Assert.assertEquals(userDTO.getId(), user.getId());
}
}
(1)编译后defalut模式会在target\classes对应路径下生成接口的class文件和默认的实体类的class文件,junit测试中如上示例所示:可以直接使用INSTANCE实例来调用相应的转换方法
(2)Spring模式:需要启动Spring容器,这里可以添加启动注解,spring-tool.xml配置扫描该转换接口,如下:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-tool.xml"})
public class UserMapperTest{
@Autowired
private UserMapper userMapper;
}
完成如上配置之后,可以直接使用注入的bean调用转换方法来完成实体类之间的转换,测试方法如下:
@Test
public void testUserToPerson() {
Person person = userMapper.userToPerson(user);
System.out.println(person);
Assert.assertNotNull(person);
}
完整的简单使用到测试步骤这里基本完成,当然这只是最基础的用法,更多特例用法以及MapStruct与其它同功能的开源工具的使用对比可自行查阅相关资料。