目录树
tkMapper使用及demo演示
一、Dao层的实现规律-前言
- 实体类与数据表存在对应关系,并且是有规律的–只要知道了数据表的结构,就能生成实体类。
单个单词等于单个单词,多个单词字段就是驼峰命名法。 - 所有实体的DAO接口中定义的方法也是有规律的,
不同点
就是实体类型不同。
UserDao
public interface UserDao{
public int insert(User user);
public User queryOneByPrimartKey(int i);
}
GoodsDao
public interface GoodsDao{
public int insert(Goods goods);
public Goods queryOneByPrimartKey(int i);
}
可以发现两个DAO其实不同点就是实体类型不一样。
所以弄一个通用DAO模板:
GeneralDao
//泛型
public interface Dao<T>{
//通用方法
public int insert(T t);
public T queryOneByPrimartKey(int i);
}
然后让其他接口来继承这个通用DAO,从而达到更高的开发效率。
UserDao
public interface UserDao extends GeneralDao{
}
GoodsDao
public interface GoodsDao extends GeneralDao{
}
通用DAO的两个方法自然也就继承过去了!
- 对于GeneralDao接口定义的数据库操作方法因为使用了
泛型
,所以无需映射文件
;
对于UserDao和GoodsDao就需要映射文件
,所有Dao的相同操作的映射文件也是有规律的。
UserDao
<insert id="insert">
insert into users(user_id,username) values (#{userId},#{username})
</insert>
@Table("users")
public class User{
@Id
@Column("user_id")
private int userId;
@Column("username")
private String username;
}
GoodsDao
<insert id="insert">
insert into goods(goods_id,goods_name) values (#{goodsId},#{goodsName})
</insert>
@Table("product")
public class Goods{
@Id
@Column("goods_id")
private int goodsId;
@Column("goods_name")
private String goodsName;
}
二、tkMapper简介
基于Mybatis提供了很多第三方插件,这些插件通常可以完成数据操作方法的封装(上面示例GeneralDao)、数据库逆向工程(根据数据表生成实体类、生成映射文件)
- MyBatis-plus
- tkMapper
tkMapper就是一个MyBatis插件,是在MyBatis基础上提供了很多工具,简化开发。
- 提供了针对
单表
的通用的数据库操作方法。即帮我们定义了通用的GenaralDao。(联表不行) - 逆向工程(根据数据表生成实体类、Dao接口、映射文件)
三、tkMapper整合
3.1基于SpringBoot完成MyBatis整合
见项目tkmapper-demo
- 创建boot项目,整合mybatis
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/zerofashion_boot?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
mybatis.type-aliases-package=com.yty.tkmapperdemo.beans
mybatis.mapper-locations=classpath:mappers/*Mapper.xml
整合MyBatis完毕!
3.2 整合tkMapper
3.2.1 添加tkMapper依赖
<!--tkMapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
3.2.2 修改启动类@MapperScan注解
@MapperScan
注解应为tk包里面的,不是org里面的。
四、tkMapper使用
4.1 创建实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "users")
public class User {
private int userId;//用户id
private String username;//用户名
private String password;//密码
private String nickname;//昵称
private String realname;//真实姓名
private String userImg;//头像
private String userMobile;//手机号
private String userEmail;//邮箱地址
private String userSex;//性别
private Date userBirth;//生日
private Date userRegtime;//注册时间
private Date userModtime;//更新时间
}
4.2 创建Dao接口
tkMapper已经完成了
单表
通用操作的封装(crud以及通过条件进行crud)----封装在Mapper接口和MySqlMapper接口;因此要对单表操作,只需自定义Dao来继承这两个接口
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
public interface UserDao extends Mapper<User>, MySqlMapper<User> {
}
继承通用已封装的接口Mapper和MySqlMapper(要给泛型)。
4.3 测试
点击UserDao,然后alt+insert进行Unit4的测试。
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TkmapperDemoApplication.class)
public class UserDaoTest {
@Autowired
private UserDao userDao;
@Test
//1.添加
public void test1(){
User user = new User();
user.setUsername("curry");
user.setPassword("123123");
user.setUserImg("img/default.png");
user.setUserRegtime(new Date());
user.setUserModtime(new Date());
int i = userDao.insert(user);
System.err.println(i);
}
结果:
五、tkMapper提供的方法
5.1新建Category实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "category")
public class Category {
@Id
@Column(name = "category_id")
private int categoryId; //分类id
private String categoryName; //分类名称
@Column(name = "category_level")
private int categoryLevel; //分类级别
@Column(name = "parent_id") //不想用这个对应数据表的列,只需要把int改为Integer,因为类反射,int不能类反射
private int parentId; //上一级类别的id
private String categoryIcon; //分类图标logo
private String categorySlogan; //口号
private String categoryPic; //分类图
private String categoryBgColor; //背景颜色
}
5.2 新建CategoryDao接口及测试类
每次都要继承Mapper和MySqlMapper接口,所以可以简化。就是自定义一个公共接口GeneralDao,放到dao层同级目录下–命名为general(不要被@MapperScan扫描到就行),以后每次只需要拿接口继承这个GenaralDao即可!
GeneralDao
public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> {
}
CategoryDao
@Repository
public interface CategoryDao extends GeneralDao<Category> {
}
CategoryDaoTest
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TkmapperDemoApplication.class)
public class CategoryDaoTest {
@Autowired
private CategoryDao categoryDao;
@Test
//1.1 测试添加
public void testInsert(){
Category category = new Category(0,"测试类别1",1,0,"a.jpg","中国最牛!","b.img","红色");
int i = categoryDao.insert(category);
//这里不用sout来获取i,从而判断是否操作成功。而用 断言来测试
assertEquals(1,i);//期望的到1,然后自动对比i。断言能通过,测试成功!
}
@Test
//1.2 测试添加--回填id
public void testInsert2(){
Category category = new Category(0,"测试类别2",1,0,"b.jpg","中国乒乓!","a.img","红色");
int i = categoryDao.insertUseGeneratedKeys(category);
System.out.println(category.getCategoryId());//回显插入数据后的主键。主键要在实体类上添加@Id注解来说明
assertEquals(1,i);
}
@Test
//2.1 测试修改
public void testUpdate(){
Category category = new Category(53,"测试类别1更新后",1,0,"a.jpg","中国最牛牛!","b.img","大红色");
int i = categoryDao.updateByPrimaryKey(category);
//另一种修改方法:根据自定义条件修改,其中Example封装修改的条件
//int i1 = categoryDao.updateByExample(Example example);
assertEquals(1,i);
}
@Test
//3.1 测试删除
public void testDelete(){
int i = categoryDao.deleteByPrimaryKey(53);
//另一种删除方法:根据自定义条件删除,其中Example封装删除的条件
//int i1 = categoryDao.deleteByExample(Example example);
assertEquals(1,i);
}
@Test
//4.1 查询所有
public void testSelect1(){
List<Category> categories = categoryDao.selectAll();
for (Category category : categories) {
System.out.println(category);
}
}
@Test
//4.2 根据主键查询
public void testSelect2(){
Category category = categoryDao.selectByPrimaryKey(54);
System.out.println(category);
}
@Test
//4.3 条件查询
public void testSelect3(){
//创建一个Example封装‘类别category’的查询条件
Example example = new Example(Category.class);
//criteria是example的内部类,来封装category的条件
Example.Criteria criteria = example.createCriteria();
//条件1:categoryLevel的值为1或者为2的数据
//下面虽然是两个方法,但是是有逻辑关联的。<and,or>
criteria.andEqualTo("categoryLevel",1);
criteria.orEqualTo("categoryLevel",2);
//条件2:categoryLevel的值不为1的数据
//criteria.andNotEqualTo("categoryLevel",1);
//条件3:模糊查询,带‘干’的数据
//%干--以‘干’字结尾 %干%--包含‘干’的数据
//criteria.andLike("categoryName", "%干%");
//反正需要什么条件,就往上面丢就行。
List<Category> categories = categoryDao.selectByExample(example);
for (Category category : categories) {
System.out.println(category);
}
}
@Test
//4.4 分页查询
public void testSelect4(){
int pageNum =2; //查询页码
int pageSize=10; //每页查询数量
int start=(pageNum-1)*pageSize;
RowBounds rowBounds = new RowBounds(start,pageSize);
//new Category()作用就是:将查询后的数据封装到里面
List<Category> categories = categoryDao.selectByRowBounds(new Category(), rowBounds);
for (Category category : categories) {
System.out.println(category);
}
//查询总记录数
int i = categoryDao.selectCount(new Category());
System.err.println("查询总数据数:"+i);
}
@Test
//4.5 带条件的分页查询
public void testSelect5(){
//条件--商品级别为1
Example example = new Example(Category.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("categoryLevel",1);
//分页--查第3页,每页3条数据
int pageNum=3;
int pageSize=3;
int start=(pageNum-1)*pageSize;
RowBounds rowBounds = new RowBounds(start,pageSize);
List<Category> categories = categoryDao.selectByExampleAndRowBounds(example, rowBounds);
for (Category category : categories) {
System.out.println(category);
}
//查询总记录数(满足条件的)
int i = categoryDao.selectCountByExample(example);
System.out.println("查询总记录数:"+i);
}
}
5.3 测试结果
1.1 测试添加
1.2 测试添加–回填id
控制台回显id:
2.1 测试修改
3.1 测试删除
4.1 查询所有
4.2 根据主键查询
主键id为54的数据
4.3 条件查询
4.4 分页查询
从id=11的数据查到id=20的数据。成功!
4.5 带条件的分页查询
六、tkMapper关联查询
操作:查询用户时带出所有订单
6.1 第一种方式:拆分
任何的联表查询都可通过多次的单表查询来完成!因为tkMapper只提供了单表查询的方法,所以只能将联表拆分为多次单表。
Orders
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "orders")
public class Orders {
private String orderId; //订单id,也是订单编号
private String userId; //用户id
private String receiverName; //收件人姓名
private String receiverMobile; //收件人电话
private String receiverAddress; //收件人地址
}
User改造
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "users")
public class User {
@Id
private Integer userId;//用户id
private String username;//用户名
private String password;//密码
private String nickname;//昵称
private String realname;//真实姓名
private String userImg;//头像
private String userMobile;//手机号
private String userEmail;//邮箱地址
private String userSex;//性别
private Date userBirth;//生日
private Date userRegtime;//注册时间
private Date userModtime;//更新时间
private List<Orders> ordersList;//对应用户的所有订单
}
UserDaoTest
@Test
//3.测试 联表查询。查询用户带出订单
public void testFix(){
//查询用户同时查询订单
Example example = new Example(User.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("username","curry");
//根据用户名查询用户
//1.先根据用户名查询用户信息
List<User> users = userDao.selectByExample(example);
User user = users.get(0);
//2.再根据用户id到订单表查询订单信息
Example example1 = new Example(Orders.class);
Example.Criteria criteria1 = example1.createCriteria();
criteria1.andEqualTo("userId",user.getUserId());
List<Orders> ordersList = ordersDao.selectByExample(example1);
//3.将查询到的订单集合 注入到user中
user.setOrdersList(ordersList);
System.out.println(user);
}
结果:
6.2 第二种方式:自定义查询
其实就是xml文件配置,然后一对多而已。
- 在使用tkM apper,dao继承Mapper和MySqlMapper之后,还可以自定义查询。
UserDao
@Repository
public interface UserDao extends GeneralDao<User> {
//除了继承的两个方法外,我在这里自定义一个方法
public User selectByUsername(String username);
}
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.yty.tkmapperdemo.dao.UserDao">
<resultMap id="userMap" type="User">
<id column="user_id" property="userId"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="nickname" property="nickname"></result>
<result column="realname" property="realname"></result>
<result column="user_img" property="userImg"></result>
<result column="user_mobile" property="userMobile"></result>
<result column="user_email" property="userEmail"></result>
<result column="user_sex" property="userSex"></result>
<result column="user_birth" property="userBirth"></result>
<result column="user_regtime" property="userRegtime"></result>
<result column="user_modtime" property="userModtime"></result>
<collection property="ordersList" ofType="Orders">
<result column="order_id" property="orderId"></result>
<result column="receiver_name" property="receiverName"></result>
<result column="receiver_mobile" property="receiverMobile"></result>
<result column="receiver_address" property="receiverAddress"></result>
</collection>
</resultMap>
<select id="selectByUsername" resultMap="userMap">
select
u.user_id,
u.username,
u.password,
u.nickname,
u.realname,
u.user_img,
u.user_mobile,
u.user_email,
u.user_sex,
u.user_birth,
u.user_regtime,
u.user_modtime,
o.order_id,
o.receiver_name,
o.receiver_mobile,
o.receiver_address
from users u inner join orders o
on u.user_id=o.user_id
</select>
</mapper>
UserDaoTest
@Test
//3.测试 联表查询。查询用户带出订单
//第二种方法:自定义方法。其实就是xml文件配置,然后一对多而已。
public void testFix2(){
User user = userDao.selectByUsername("curry");
System.out.println(user);
}
七、逆向工程
逆向工程:根据创建好的数据表,生成实体类、Dao、xml映射文件
7.1 添加逆向工程依赖
此依赖是一个mybatis的maven插件
- 逆向工程需要这个插件,插件内部又需要这两个依赖。
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<!--给上面插件添加依赖-->
<dependencies>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--tk.mybatis映射-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>3.4.4</version>
</dependency>
</dependencies>
</plugin>
7.2 逆向工程配置
- 在resources/generator目录下创建generatorConfig.xml
generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--引入数据库连接配置-->
<!-- <properties resource="jdbc.properties"/>-->
<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!--配置 GeneralDao-->
<!--这是一个继承的Mapper<T>,MySqlMapper<T>的接口,自定义的。-->
<plugin type="tk.mybatis.mapper.generator.MapperPlugin">
<property name="mappers" value="com.yty.tkmapperdemo.general.GeneralDao"/>
</plugin>
<!--配置数据库连接-->
<jdbcConnection
driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/zerofashion_boot"
userId="root"
password="123456">
</jdbcConnection>
<!--配置实体类存放路径-->
<javaModelGenerator targetPackage="com.yty.tkmapperdemo.beans" targetProject="src/main/java"/>
<!--配置 XML 存放路径-->
<sqlMapGenerator targetPackage="/" targetProject="src/main/resources/mappers"/>
<!--配置 Dao 存放路径-->
<javaClientGenerator targetPackage="com.yty.tkmapperdemo.dao" targetProject="src/main/java" type="XMLMAPPER"/>
<!--配置需要指定生成的数据库和表,%代表所有表-->
<table tableName="%">
<!--mysql配置-->
<!-- <generatedKey column="id" sqlStatement="Mysql" identity="true"/>-->
</table>
<!-- <table tableName="user_addr">-->
<!-- <!–mysql配置–>-->
<!-- <generatedKey column="addr_id" sqlStatement="Mysql" identity="true"/>-->
<!-- </table>-->
<!-- <table tableName="users">-->
<!-- <!–mysql配置–>-->
<!-- <generatedKey column="user_id" sqlStatement="Mysql" identity="true"/>-->
<!-- </table>-->
</context>
</generatorConfiguration>
使用的配置文件:(上面的是为了更好的理解,太复杂了,下面的是直接能用的,不适合新人)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- 引入数据库连接配置 -->
<!-- <properties resource="jdbc.properties"/>-->
<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!-- 配置 GeneralDAO -->
<plugin type="tk.mybatis.mapper.generator.MapperPlugin">
<property name="mappers" value="com.yty.tkmapperdemo.general.GeneralDao"/>
</plugin>
<!-- 配置数据库连接 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/zerofashion_boot"
userId="root" password="123456">
</jdbcConnection>
<!-- 配置实体类存放路径 -->
<javaModelGenerator targetPackage="com.yty.tkmapperdemo.beans" targetProject="src/main/java"/>
<!-- 配置 XML 存放路径 -->
<sqlMapGenerator targetPackage="/" targetProject="src/main/resources/mappers"/>
<!-- 配置 DAO 存放路径 -->
<javaClientGenerator targetPackage="com.yty.tkmapperdemo.dao" targetProject="src/main/java" type="XMLMAPPER"/>
<!-- 配置需要指定生成的数据库和表,% 代表所有表 -->
<table tableName="%"></table>
</context>
</generatorConfiguration>
7.3 ❤将配置文件设置到逆向工程的maven插件中
<configuration>
<configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml}</configurationFile>
</configuration>
7.4 执行逆向生成
双击执行!