Este artigo participou do evento "Newcomer Creation Ceremony" para iniciar juntos o caminho da criação de ouro.
@[toc] No processo de desenvolvimento do mybatis, frequentemente encontramos esses problemas: por exemplo, a data na tabela mysql é uma string, mas queremos operar de acordo com o tipo Date em java. Portanto, precisamos usar o typeHandler em mybatis. Este artigo é um campo createDate armazenado no tipo String no banco de dados, e seu formato é "aaaa-MM-ddHH:mm:ss", que é convertido em uma operação Date pelo TypeHandler.
1. Manipulador de Tipos
O TypeHandler personalizado precisa herdar o BaseTypeHandler. código mostrar como abaixo:
import com.google.common.base.Strings;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(Date.class)
public class MyDateTypeHandler extends BaseTypeHandler<Date> {
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
private Date convert(String source) {
Date result = new Date(0);
try {
if (!Strings.isNullOrEmpty(source)) {
result = dateFormat.parse(source);
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Date parameter, JdbcType jdbcType) throws SQLException {
String result = dateFormat.format(parameter);
ps.setString(i, result);
}
@Override
public Date getNullableResult(ResultSet rs, String columnName) throws SQLException {
String source = rs.getString(columnName);
return convert(source);
}
@Override
public Date getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String source = rs.getString(columnIndex);
return convert(source);
}
@Override
public Date getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String source = cs.getString(columnIndex);
return convert(source);
}
}
复制代码
Nesta classe, primeiro você precisa definir o tipo de dado no banco de dados através da anotação @MappedJdbcTypes(JdbcType.VARCHAR). @MappedTypes(Date.class) define os tipos de dados em objetos Java.
MyDateTypeHandler herda BaseTypeHandler e precisa implementar quatro métodos, um dos quais é o método setNonNullParameter para converter Date em String e os outros três são métodos para converter String no ResultSet do resultado da operação do banco de dados em String. Neste exemplo, se a string estiver vazia, será criado um objeto cujo padrão é Date(0).
2.generatorConfig.xml
Como os geradores serão usados para gerar o código ORM ao contrário, é necessário adicionar a tag columnOverride à definição da tabela para configurar o Handler, para que o código necessário seja criado durante a engenharia reversa.
<table tableName="users" domainObjectName="Users">
<columnOverride column="createDate" jdbcType="VARCHAR" javaType="java.util.Date" typeHandler="com.dhb.gts.javacourse.week5.typehandler.MyDateTypeHandler"/>
</table>
复制代码
3. Geração de Código
O código necessário pode ser gerado por grale->other->MybatisGenerate.
Você pode ver que na entidade de código gerada neste momento, o tipo de createDate dos usuários é Date.
主要的操作是在UsersMapper中进行了修改,@insert和select方法的@Results中都添加了MyDateTypeHandler的处理。
package com.dhb.gts.javacourse.week5.mapper;
import com.dhb.gts.javacourse.week5.entity.Users;
import com.dhb.gts.javacourse.week5.entity.UsersExample;
import com.dhb.gts.javacourse.week5.typehandler.MyDateTypeHandler;
import java.util.List;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import org.apache.ibatis.type.JdbcType;
public interface UsersMapper {
@SelectProvider(type=UsersSqlProvider.class, method="countByExample")
long countByExample(UsersExample example);
@DeleteProvider(type=UsersSqlProvider.class, method="deleteByExample")
int deleteByExample(UsersExample example);
@Insert({
"insert into users (id, username, ",
"`password`, createDate)",
"values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, ",
"#{password,jdbcType=VARCHAR}, #{createdate,jdbcType=VARCHAR,typeHandler=com.dhb.gts.javacourse.week5.typehandler.MyDateTypeHandler})"
})
int insert(Users record);
@InsertProvider(type=UsersSqlProvider.class, method="insertSelective")
int insertSelective(Users record);
@SelectProvider(type=UsersSqlProvider.class, method="selectByExample")
@Results({
@Result(column="id", property="id", jdbcType=JdbcType.INTEGER),
@Result(column="username", property="username", jdbcType=JdbcType.VARCHAR),
@Result(column="password", property="password", jdbcType=JdbcType.VARCHAR),
@Result(column="createDate", property="createdate", typeHandler=MyDateTypeHandler.class, jdbcType=JdbcType.VARCHAR)
})
List<Users> selectByExample(UsersExample example);
@UpdateProvider(type=UsersSqlProvider.class, method="updateByExampleSelective")
int updateByExampleSelective(@Param("record") Users record, @Param("example") UsersExample example);
@UpdateProvider(type=UsersSqlProvider.class, method="updateByExample")
int updateByExample(@Param("record") Users record, @Param("example") UsersExample example);
}
复制代码
4.Starter
在springboot中,通过Startler启动,分别插入数据和select进行测试。 启动器:
package com.dhb.gts.javacourse.week5.generator;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(basePackages = {"com.dhb.gts.javacourse.week5.mapper,com.dhb.gts.javacourse.week5.entity"})
public class GeneratorStarter {
public static void main(String[] args) {
SpringApplication.run(GeneratorStarter.class, args);
}
}
复制代码
rest的controller:
package com.dhb.gts.javacourse.week5.generator;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.dhb.gts.javacourse.week5.entity.Users;
import com.dhb.gts.javacourse.week5.entity.UsersExample;
import com.dhb.gts.javacourse.week5.mapper.UsersMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Random;
@RestController
public class GeneratorController {
@Autowired
private UsersMapper usersMapper;
private Random random = new Random();
@RequestMapping("/generatorquery")
@ResponseBody
public String generatorQuery(HttpServletRequest request, HttpServletResponse response) {
UsersExample example = new UsersExample();
example.createCriteria();
List<Users> list = usersMapper.selectByExample(example);
return JSON.toJSONString(list, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteDateUseDateFormat);
}
@RequestMapping("/generatorinsert")
@ResponseBody
public String generatorInsert(HttpServletRequest request, HttpServletResponse response) {
Users users = new Users();
users.setPassword(String.valueOf(System.currentTimeMillis()));
users.setUsername("generatorinsert"+random.nextInt(100));
users.setCreatedate(new Date());
usersMapper.insert(users);
return "success";
}
}
复制代码
此外还需注意的是,在springboot的yml文件中要增加如下内容:
# mybatis typehandler
mybatis.type-handlers-package: com.dhb.gts.javacouse.week5.typehandler
复制代码
5.运行测试
建表语句如下:
CREATE TABLE users (
id int(11) AUTO_INCREMENT NOT NULL,
username varchar(50) NULL,
password varchar(50) NULL,
createDate varchar(50) NULL,
PRIMARY KEY(id)
)
ENGINE = InnoDB
复制代码
通过insert接口http://127.0.0.1:8084/generatorinsert插入数据之后,可以看到数据库中的值:
通过query接口查询如下:
可以看到我们的MyDateTypeHandler对数据进行了转换,在insert和select方法中都起到了作用。