目录
- 零、起因
- 一、怎么使用Free MyBatis Tool插件?
- 1 基本使用
- 2 进阶使用(搞清楚Options的用法)
- 2.1 概览
- 2.2 详述
- 2.2.0 Options(一项都不勾选)
- 2.2.1 Use-Lombok【消除UserDO中的getter和setter代码】
- 2.2.2 Comment(实体注释)【和“2.2.1”相比,没任何变化...】
- 2.2.3 Use-Schema(使用Schema前缀)【和“2.2.1”相比,没任何变化...】
- 2.2.4 Overwrite-Java【和“2.2.1”相比,没任何变化...】
- 2.2.5 Overwrite-Xml【和“2.2.1”相比,没任何变化...】
- 2.2.6 Repository-Annotation(Repository注解)【在UserMapper.java中打上@Repository注解】
- 2.2.7 toString/hashCode/equals【给UserDO增加这些方法】
- 2.2.8 Parent-Interface(Dao公共父接口)【别勾选这个!】
- 2.2.9 JSR310:Date and Time API【UserDO的Date会变成LocalDateTime】
- 2.2.10 JPA-Annotation(JPA注解)【UserDO会带上JPA注解】
- 2.2.11 Actual-Column(实际的列名)【UserDO字段名和表的列名一致】
- 2.2.12 Use-Alias(启用别名查询)【UserMapper.xml的列名会发生变化】
- 2.2.13 Use-Example【别勾选这个!】
- 2.2.14 Page(分页,需开启Use-Example)【自己实现分页吧,别勾选这个!】
- 2.2.15 Add-ForUpdate(需开启Use-Example)【自己实现悲观锁吧,别勾选这个!】
- 2.3 结论【推荐勾选哪些呢?】
零、起因
- 后端开发少不了设计表(例如:xxx表)。
- 设计好表后,少不了需要去实现xxxDO、xxxMapper.java、xxxMapper.xml(ORM框架选Mybatis的情况)。
- 这些都是模板代码,让人来写真费劲啊! 【问题】
- 【解决办法】:利用“Free MyBatis Tool插件”消灭dao层的繁琐编码。
一、怎么使用Free MyBatis Tool插件?
1 基本使用
- Options中那么多选项,具体是啥意思?
2 进阶使用(搞清楚Options的用法)
2.1 概览
- Use-Lombok
- Comment(实体注释)
- Use-Schema(使用Schema前缀)
- Overwrite-Java
- Overwrite-Xml
- Repository-Annotation(Repository注解)
- toString/hashCode/equals
- Parent-Interface(Dao公共父接口)
- JSR310:Date and Time API
- JPA-Annotation(JPA注解)
- Actual-Column(实际的列名)
- Use-Alias(启用别名查询)
- Use-Example
- Page(分页,需开启Use-Example)
- Add-ForUpdate(需开启Use-Example)
2.2 详述
2.2.0 Options(一项都不勾选)
- UserDO
package com.forrest.demo.model;
import java.io.Serializable;
import java.util.Date;
/**
* user
*/
public class UserDO implements Serializable {
private Integer id;
private String username;
private String passwordHash;
private String email;
private Date registrationDate;
private Date lastLoginTime;
private static final long serialVersionUID = 1L;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPasswordHash() {
return passwordHash;
}
public void setPasswordHash(String passwordHash) {
this.passwordHash = passwordHash;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getRegistrationDate() {
return registrationDate;
}
public void setRegistrationDate(Date registrationDate) {
this.registrationDate = registrationDate;
}
public Date getLastLoginTime() {
return lastLoginTime;
}
public void setLastLoginTime(Date lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}
}
- UserMapper.java
package com.forrest.demo.dao;
import com.forrest.demo.model.UserDO;
public interface UserMapper {
int deleteByPrimaryKey(Integer id);
int insert(UserDO record);
int insertSelective(UserDO record);
UserDO selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(UserDO record);
int updateByPrimaryKey(UserDO record);
}
- UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.forrest.demo.dao.UserMapper">
<resultMap id="BaseResultMap" type="com.forrest.demo.model.UserDO">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="username" jdbcType="VARCHAR" property="username" />
<result column="password_hash" jdbcType="VARCHAR" property="passwordHash" />
<result column="email" jdbcType="VARCHAR" property="email" />
<result column="registration_date" jdbcType="TIMESTAMP" property="registrationDate" />
<result column="last_login_time" jdbcType="TIMESTAMP" property="lastLoginTime" />
</resultMap>
<sql id="Base_Column_List">
id, username, password_hash, email, registration_date, last_login_time
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from user
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from user
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.forrest.demo.model.UserDO" useGeneratedKeys="true">
insert into user (username, password_hash, email,
registration_date, last_login_time)
values (#{username,jdbcType=VARCHAR}, #{passwordHash,jdbcType=VARCHAR}, #{email,jdbcType=VARCHAR},
#{registrationDate,jdbcType=TIMESTAMP}, #{lastLoginTime,jdbcType=TIMESTAMP})
</insert>
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.forrest.demo.model.UserDO" useGeneratedKeys="true">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username != null">
username,
</if>
<if test="passwordHash != null">
password_hash,
</if>
<if test="email != null">
email,
</if>
<if test="registrationDate != null">
registration_date,
</if>
<if test="lastLoginTime != null">
last_login_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="username != null">
#{username,jdbcType=VARCHAR},
</if>
<if test="passwordHash != null">
#{passwordHash,jdbcType=VARCHAR},
</if>
<if test="email != null">
#{email,jdbcType=VARCHAR},
</if>
<if test="registrationDate != null">
#{registrationDate,jdbcType=TIMESTAMP},
</if>
<if test="lastLoginTime != null">
#{lastLoginTime,jdbcType=TIMESTAMP},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.forrest.demo.model.UserDO">
update user
<set>
<if test="username != null">
username = #{username,jdbcType=VARCHAR},
</if>
<if test="passwordHash != null">
password_hash = #{passwordHash,jdbcType=VARCHAR},
</if>
<if test="email != null">
email = #{email,jdbcType=VARCHAR},
</if>
<if test="registrationDate != null">
registration_date = #{registrationDate,jdbcType=TIMESTAMP},
</if>
<if test="lastLoginTime != null">
last_login_time = #{lastLoginTime,jdbcType=TIMESTAMP},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.forrest.demo.model.UserDO">
update user
set username = #{username,jdbcType=VARCHAR},
password_hash = #{passwordHash,jdbcType=VARCHAR},
email = #{email,jdbcType=VARCHAR},
registration_date = #{registrationDate,jdbcType=TIMESTAMP},
last_login_time = #{lastLoginTime,jdbcType=TIMESTAMP}
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
2.2.1 Use-Lombok【消除UserDO中的getter和setter代码】
- 看了“2.2.0”很自然就知道
Use-Lombok
的好处了:可以消除UserDO中的getter和setter代码。 - UserDO
/**
* user
*/
@Data
public class UserDO implements Serializable {
private Integer id;
private String username;
private String passwordHash;
private String email;
private Date registrationDate;
private Date lastLoginTime;
private static final long serialVersionUID = 1L;
}
- UserMapper.java
- 没变化,和“2.2.0”一样
- UserMapper.xml
- 没变化,和“2.2.0”一样
2.2.2 Comment(实体注释)【和“2.2.1”相比,没任何变化…】
- 我以为会给UserDO增加注释…但并没有。
- 和“2.2.1”相比,没任何变化…
2.2.3 Use-Schema(使用Schema前缀)【和“2.2.1”相比,没任何变化…】
- 在“2.2.2”基础上没有增加任何内容。
- 这个Schema可以被简单理解为user表在哪个数据库中。
2.2.4 Overwrite-Java【和“2.2.1”相比,没任何变化…】
- 即使已经有UserDO.java和UserMapper.java了,让开发者选择是否覆写这两个文件。
2.2.5 Overwrite-Xml【和“2.2.1”相比,没任何变化…】
- 同理,即使已经有UserMapper.xml了,让开发者选择是否覆写这个xml文件。
2.2.6 Repository-Annotation(Repository注解)【在UserMapper.java中打上@Repository注解】
- 在UserMapper.java中打上@Repository注解。
2.2.7 toString/hashCode/equals【给UserDO增加这些方法】
- 给UserDO增加toString/hashCode/equals方法:
package com.forrest.demo.model;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
/**
* user
*/
@Data
public class UserDO implements Serializable {
...
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (that == null) {
return false;
}
if (getClass() != that.getClass()) {
return false;
}
UserDO other = (UserDO) that;
return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
&& (this.getUsername() == null ? other.getUsername() == null : this.getUsername().equals(other.getUsername()))
&& (this.getPasswordHash() == null ? other.getPasswordHash() == null : this.getPasswordHash().equals(other.getPasswordHash()))
&& (this.getEmail() == null ? other.getEmail() == null : this.getEmail().equals(other.getEmail()))
&& (this.getRegistrationDate() == null ? other.getRegistrationDate() == null : this.getRegistrationDate().equals(other.getRegistrationDate()))
&& (this.getLastLoginTime() == null ? other.getLastLoginTime() == null : this.getLastLoginTime().equals(other.getLastLoginTime()));
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
result = prime * result + ((getUsername() == null) ? 0 : getUsername().hashCode());
result = prime * result + ((getPasswordHash() == null) ? 0 : getPasswordHash().hashCode());
result = prime * result + ((getEmail() == null) ? 0 : getEmail().hashCode());
result = prime * result + ((getRegistrationDate() == null) ? 0 : getRegistrationDate().hashCode());
result = prime * result + ((getLastLoginTime() == null) ? 0 : getLastLoginTime().hashCode());
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", username=").append(username);
sb.append(", passwordHash=").append(passwordHash);
sb.append(", email=").append(email);
sb.append(", registrationDate=").append(registrationDate);
sb.append(", lastLoginTime=").append(lastLoginTime);
sb.append(", serialVersionUID=").append(serialVersionUID);
sb.append("]");
return sb.toString();
}
}
- @Data注解会自动生成一个类的toString、hashCode和equals方法。**因此,没必要勾选“toString/hashCode/equals”。**即使有特殊需求,也是自己去覆写这些方法,而不是用“Free MyBatis Tool插件”生成的。
2.2.8 Parent-Interface(Dao公共父接口)【别勾选这个!】
- UserMapper.java
package com.forrest.demo.dao;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper {
}
- MyBatisBaseDao
package com.forrest.demo.dao;
import java.io.Serializable;
import java.util.List;
import org.apache.ibatis.annotations.Param;
/**
* DAO公共基类,由MybatisGenerator自动生成请勿修改
* @param <Model> The Model Class 这里是泛型不是Model类
* @param <PK> The Primary Key Class 如果是无主键,则可以用Model来跳过,如果是多主键则是Key类
* @param <E> The Example Class
*/
public interface MyBatisBaseDao<Model, PK extends Serializable, E> {
int deleteByPrimaryKey(PK id);
int insert(Model record);
int insertSelective(Model record);
Model selectByPrimaryKey(PK id);
int updateByPrimaryKeySelective(Model record);
int updateByPrimaryKey(Model record);
}
- 很显然,别勾选“Parent-Interface(Dao公共父接口)”
2.2.9 JSR310:Date and Time API【UserDO的Date会变成LocalDateTime】
- UserDO的变化
- 对比“2.2.1”,UserMapper.java和UserMapper.xml没变化。
JSR-310: Date and Time API
是Java 8中引入的一个新日期和时间API,它提供了一系列用于日期、时间、时区和时钟的类和接口。这个API旨在解决旧版Date和Calendar类存在的问题,并提供了更加易用、更加强大、类型安全的日期和时间操作。
在使用Free MyBatis Tool插件时,如果选择了支持JSR-310,插件会根据这个新的日期时间API生成相应的代码。这意味着在xxxDO和Mapper接口中,日期时间字段将会使用JSR-310中的类,例如LocalDate、LocalTime、LocalDateTime、ZonedDateTime等,而不是Java 7及以前版本中使用的java.util.Date或java.sql.Date。
- 按理来说,应该勾选“JSR310:Date and Time API”。但实际开发中,不少字段仍然用的是Date… (如果自己没有决策权,也只能被迫用Date,懂的都懂:))
2.2.10 JPA-Annotation(JPA注解)【UserDO会带上JPA注解】
- UserDO会带上JPA注解:
package com.forrest.demo.model;
import java.io.Serializable;
import java.time.LocalDateTime;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
import org.hibernate.validator.constraints.NotEmpty;
/**
* user
*/
@Table(name="user")
@Data
public class UserDO implements Serializable {
@Id
@GeneratedValue
@GeneratedValue(generator = "JDBC")
private Integer id;
@NotEmpty
private String username;
@NotEmpty
private String passwordHash;
@NotEmpty
private String email;
private LocalDateTime registrationDate;
private LocalDateTime lastLoginTime;
private static final long serialVersionUID = 1L;
}
- 对比“2.2.9”,UserMapper.java和UserMapper.xml没变化。
JPA(Java Persistence API)是Java持久化API的简称,它是Java EE规范的一部分,旨在简化Java对象和关系数据库之间的映射和持久化操作。
实际开发中,我咋很少见到JPA注解…
2.2.11 Actual-Column(实际的列名)【UserDO字段名和表的列名一致】
- UserDO字段名和表的列名一致:
类似的,在UserMapper.xml和UserMapper.java中,也从passwordHash变成了password_hash(其他字段同理)。
- 但这显然不符合Java命名习惯,因此,不要勾选“Actual-Column(实际的列名)”。
2.2.12 Use-Alias(启用别名查询)【UserMapper.xml的列名会发生变化】
- UserMapper.xml的列名会发生变化:
- 一般来说,如果是单表查询,我们是不需要这么写的:
select user.id from user where id = 1;
。因此,没必要勾选“Use-Alias(启用别名查询)”。
2.2.13 Use-Example【别勾选这个!】
- 会增加一个UserDOExample
public class UserDOExample {
protected String orderByClause;
protected boolean distinct;
protected List<Criteria> oredCriteria;
...
}
- UserMapper.java会这么写:
public interface UserMapper {
long countByExample(UserDOExample example);
int deleteByExample(UserDOExample example);
int deleteByPrimaryKey(Integer id);
...
}
只能说…别勾选这个!
2.2.14 Page(分页,需开启Use-Example)【自己实现分页吧,别勾选这个!】
2.2.15 Add-ForUpdate(需开启Use-Example)【自己实现悲观锁吧,别勾选这个!】
2.3 结论【推荐勾选哪些呢?】
- 打开设置,如下图所示:
- 此外,我觉得生成的UserMapper.java中的方法命名不符合习惯,还得自行做一些调整。
public interface UserMapper {
int deleteByPrimaryKey(Integer id);
...
}