栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

mybatis使用步骤(mybatis详细教程)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

mybatis使用步骤(mybatis详细教程)

文章目录

01. 介绍

1.1、三层架构1.2、MyBatis 02. jdbc问题总结03. 快速使用MyBatis

3.1、项目结构3.2、基本使用步骤

3.2.1 概述3.2.2 导入jar包

MyBatisMySQLServlet、JspLombok 3.2.3 创建表对应的Pojo类3.2.4 添加配置文件

SqlMapConfig.xmlmapper.xmldb.properties 3.2.5 测试开始(增删改查)

测试步骤查增删改 3.3、SQL语句中的参数

3.3.1、一个简单参数3.3.2、多个参数

1、使用@Param(常用)2、使用对象(主要使用)3、使用位置(了解)4、使用Map(了解) 3.4、使用小结

3.4.1、mybatis配置/架构说明

1、MyBatis架构2、说明

配置文件说明架构说明 3.4.2、使用到的各个类、接口说明3.4.3、parameterType和resultType3.4.4、typeAliases(类型别名)3.4.5、占位符#{} 和 ${}(面试会问)

#{}${}区别 3.4.6、selectOne和selectList 04. Mapper动态代理方式开发

4.1、原始Dao开发的流程4.2、原始Dao开发中存在的问题4.3、Mapper动态代理开发规范4.4、动态代理开发实战

1、实体类2、mapper配置文件3、Dao接口4、测试类 05. 封装MyBatis输出结果

5.1、resultType5.2、resultMap5.3、resultType和resultMap的区别5.4、pojo类中属性与表列名不一致处理方式 06. QueryVo07. 动态SQL

7.1、简介7.2、基础使用7.3、使用include提取SQL语句中相同的部分7.4、使用foreach标签 08. MySQL自增主键返回

需求实现 09. 控制台打印日志

1、使用mybatis自带的2、Log4j的使用 10、SqlMapConfig文件中一次性指定多个mapper11. 关联查询

11.1 一对一查询

11.1.1 实现方式一:使用ResultType

1、根据查询结果创建一个pojo类,用来存储返回的数据2、创建一个mapper3、编写Dao接口4、开始测试 11.1.2 实现方式二:使用ResultMap

1、在Order类中加入User属性2、使用`resultMap`标签中的`association`进行关联3、在Dao接口中添加相应的方法4、开始测试 11.2 一对多查询

1、在User中添加`List orders`属性2、使用`resultMap`标签中的`collection`进行关联

注意:这里有一个易错的经典错误 3、在Dao接口中添加相应的方法4、开始测试 11.3 嵌套查询

11.3.1 表结构11.3.2 需求11.3.3 实现

1、创建pojo类2、创建Dao接口3、创建`mapper_employees.xml`资源文件4、在`SqlMapConfig.xml`文件中注册`mapper`5、开始测试 12. pagehelper分页

1、导包2、在`SqlMapConfig.xml`文件中配置3、开始使用pagehelper4、PageInfo类里面的属性

01. 介绍 1.1、三层架构

三层架构包含的三层:

界面层(User Interface layer):主要功能是接受用户的数据,显示请求的处理结果。使用 web 页面和 用户交互,手机 app 也就是表示层的,用户在 app 中操作,业务逻辑在服务器端处理。业务逻辑层(Business Logic Layer):接收表示传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取数据。数据访问层(Data access layer):与数据库打交道。主要实现对数据的增、删、改、查。将存储在数据库中的数据提交 给业务层,同时将业务层处理的数据保存到数据库。

三层架构对应的包对应的类对应的高级框架
界面层controller(控制器)xxxServlet类SpringMVC
业务逻辑层service(服务)xxxService类Spring
数据访问层dao(Data Access Object数据访问对象)xxxDao类MyBatis
1.2、MyBatis

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、 结果集检索等jdbc繁杂的过程代码。

Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回.


02. jdbc问题总结
    数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。如果使用数据库连接池可解决此问题.Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变 java代码.使用PreparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护.对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象(持久化类)解析比较方便.

03. 快速使用MyBatis

这里没有使用到任何开发模式,只是描述了快速使用MyBatis的步骤

3.1、项目结构

3.2、基本使用步骤 3.2.1 概述
    导入jar包:mybatis、mysql、lombok(在pom文件中加入mybatis坐标)创建实体类(每一张表对应一个类,也叫pojo类(Plain Old Java Object:持久化类))创建sql映射文件:mapper_xxx.xml文件(一个表对应一个映射文件)创建mybatis主配置文件:SqlMapConfig.xml文件(一个项目对应一个主配置文件,别忘了在里面指定mapper文件)创建使用mybatis的对象Sqlsession,通过它的方法执行sql语句
3.2.2 导入jar包 MyBatis

    org.mybatis
    mybatis
    3.4.1

MySQL

    mysql
    mysql-connector-java
    8.0.18

Servlet、Jsp

导入Servlet、jsp包后就不需要手动导入tomcat里面的依赖包了。



    javax.servlet
    javax.servlet-api
    3.1.0
    provided





    javax.servlet.jsp
    jsp-api
    2.1
    provided

Lombok

Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。

Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。


    org.projectlombok
    lombok
    1.18.12
    provided

需要双击该jar包安装好后才能使用(路径选择为D:Developer_Toolseclipseeclipseeclipse.exe)

注解说明
@Data@Data注解在类上,会为类的所有属性自动生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
@Getter/@Setter如果觉得@Data太过残暴(因为@Data集合了@ToString、@EqualsAndHashCode、@Getter/@Setter、@RequiredArgsConstructor的所有特性)不够精细,可以使用@Getter/@Setter注解,此注解在属性上,可以为相应的属性自动生成Getter/Setter方法
@Cleanup该注解能帮助我们自动调用close()方法,很大的简化了代码。
@ToString类使用@ToString注解,Lombok会生成一个toString()方法,默认情况下,会输出类名、所有属性(会按照属性定义顺序),用逗号来分割。
@NoArgsConstructor生成无参构造
@AllArgsConstructor生成全参构造

使用示例

@Getter					// get方法
@Setter					// set方法
@NoArgsConstructor		// 无参构造
@AllArgsConstructor		// 全参构造
@ToString				// tostring方法
public class Employees {
    private Integer employeeNumber;
    private String lastName;
    private String firstName;
    private String extension;
    private String email;
    private String officeCode;
    private Integer reportsTo;
    private String jobTitle;
}
3.2.3 创建表对应的Pojo类
package com.atSchool.Pojo;


@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class HouseUser {
	private Integer UID; // 这里必须和表中的列名一样
	private String uName;
	private String uPassWord;
}
3.2.4 添加配置文件

都是在项目的/MavenProject/src/main/resources目录下创建

SqlMapConfig.xml

内容在如下网址中有

https://mybatis.org/mybatis-3/zh/getting-started.html

示例:SqlMapConfig.xml






    
    
        
        
    

    
    
        
    

    
    
    

        
        

            
            

            
            
                

                
                

                
                
            
        
    

    
    
        
    

mapper.xml

这里可以不用取名为mapper.xml

sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在 SqlMapConfig.xml中加载.

示例:mapper_book.xml







    
    
    select id,name,email,age from student where id=#{studentId}



#{studentId} , studentId 是自定义的变量名称,和方法参数名无关。
3.3.2、多个参数 1、使用@Param(常用)

思想:当需要使用多个参数时,通过类似取别名的概念进行参数标识。

使用:

    接口中

    List selectStudent( @Param(“personName”) String name ) { … }
    

    mapper文件中

    
    	select id, name, email, age from student
        where name=#{paramName, javaType=java.lang.String, jdbcType=VARCHAR}
    	or age=#{paramAge,javaType=java.lang.Integer, jdbcType=INTEGER}
    
    

    简化后的语法:

    mybatis会通过反射获取javaType和jdbcType的值,不需要我们提供。

    语法:#{属性名}
    
    
    	select id, name, email, age from student
        where name=#{arg0} or age=#{arg1}
    
    

缺点:

按位置来,如果参数变化,或者位置写错,都会导致运行出错,不直观、方便,一般我们不使用。

4、使用Map(了解)

使用:

    接口中

    List selectMultiByMap(Mapkstring,object> map);
    

    mapper中

    #{key值}
    
    
    		select * from sys_user
    	
    
    	
    
    
5.3、resultType和resultMap的区别

resultType

查询出的字段在相应的pojo中必须有和它相同的字段对应,或者基本数据类型

适合简单查询

resultMap

需要自定义字段,或者多表查询,一对多等关系,比resultType更强大

适合复杂查询

5.4、pojo类中属性与表列名不一致处理方式
    使用resultMap使用resultType + sql中的取别名

06. QueryVo

开发中通过可以使用pojo传递查询条件.

但是查询条件可能是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如查询用户信息的时候,将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数.

包装对象:Pojo类中的一个属性是另外一个pojo.

需求:根据用户名模糊查询用户信息,查询条件放到QueryVo的user属性中(vo:viewObject)。

QueryVo类

package com.atSchool.Pojo;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class QueryVo {
	private HouseUser houseUser;
}

mapper映射文件中




7.4、使用foreach标签

需求:

之前我们都是以传参/动态sql的方式对sql语句进行处理,但是如果遇到了IN的查询条件,就只能使用foreach进行处理了。例如以下语句:

SELECT * FROM `sys_user` WHERe UID IN (1,3,4,11)

1、在QueryVo中添加一个集合,用于存储sql语句IN后面的条件值

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class QueryVo {
	private HouseUser houseUser;
	private List ids; // sql语句中有in条件时用到
}

2、在mapper.xml文件中添加


    
    
    
    
    



    SELECT * FROM `sys_user`
    WHERe UID
    IN
    
    
    
    
    
    
        #{item}
    

3、在UserDao接口中添加相应的方法(动态代理)

// 根据多个id查询
List queryUserByIds(QueryVo queryVo);

3、开始测试

package com.atSchool.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.atSchool.Dao.UserDao;
import com.atSchool.Pojo.HouseUser;
import com.atSchool.Pojo.QueryVo;

public class TestDao {
	public static void main(String[] args) throws IOException {
		InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
		SqlSession openSession = new SqlSessionFactoryBuilder().build(resourceAsStream).openSession();
		UserDao mapper = openSession.getMapper(UserDao.class);

		List asList = Arrays.asList(1, 2, 3, 11);
		List queryUserByIds = mapper.queryUserByIds(new QueryVo(null, asList));
		for (HouseUser houseUser : queryUserByIds) {
			System.out.println(houseUser);
		}
	}
}

08. MySQL自增主键返回 需求

由于有些表的id字段是自增的,所以当添加一条新的数据后可能会需要知道这个新增数据的自增字段的值是多少。

SQL语句

SELECT LAST_INSERT_ID() 实现


    
    
        SELECT LAST_INSERT_ID()
    
    INSERT INTO `sys_user` (uName,uPassWord) VALUES (#{uName},#{uPassWord})

public static void addUser() {
    // 4. 创建`SqlSession`对象
    SqlSession openSession = Tools.getSqlSessionion();

    // 5. 执行`SqlSession`对象执行插入
    HouseUser houseUser = new HouseUser("Maria", "123456");
    int insert = openSession.insert("insertUser", houseUser);
    System.out.println("受影响的行数为:" + insert);

    // 6. 提交
    openSession.commit();

    
    System.out.println(houseUser);
    
    // 7. 释放资源
    openSession.close();
}

09. 控制台打印日志 1、使用mybatis自带的

在SqlMapConfig配置文件中加入


    
    

2、Log4j的使用

日志是应用软件中不可缺少的部分,Apache的开源项目log4j是一个功能强大的日志组件,提供方便的日志记录。

使用时需要添加一个log4j.properties文件。就和学习Hadoop时一样

log4j.rootLogger=debug, stdout, R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=./log/Gosion.log
log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=5
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

10、SqlMapConfig文件中一次性指定多个mapper

之前在SqlMapConfig文件中指定mapper都是一个一个指定的,但其实也可以一次性指定。

之前:


    

之后:


    

使用该方式的前提条件:

    mapper文件所在位置必须和接口在同一包下。mapper文件的名字必须和接口的名字一样。maven默认只识别resource中的资源文件,所以要使用该方式还得在SqlMapConfig文件中使用资源插件告诉maven,mapper文件所在包中的文件也要识别

11. 关联查询

表说明:

user表

orders表

表对应的pojo类:

  package com.atSchool.Pojo;
  
  import lombok.Getter;
  import lombok.Setter;
  import lombok.ToString;
  
  
  @Getter
  @Setter
  @NoArgsConstructor
  @AllArgsConstructor
  @ToString
  public class User {
  	private Integer id;
  	private String username;
  	private String birthday;
  	private String sex;
  	private String address;
  }
  package com.atSchool.Pojo;
  
  import lombok.Getter;
  import lombok.Setter;
  import lombok.ToString;
  
  
  @Getter
  @Setter
  @NoArgsConstructor
  @AllArgsConstructor
  @ToString
  public class Order {
  	private Integer id;
  	private String userId;
  	private String number;
  	private String creatTime;
  	private String note;
  }
11.1 一对一查询

写在前面:如果数据库换了的话要记得在配置文件中修改连接到的数据库。

一对一查询:例如订单关联用户,是一对一的关系。

SELECT o.id,o.user_id,o.number,o.createtime,o.note,u.username,u.birthday,u.sex,u.address
FROM `orders` o LEFT JOIN `user` u ON u.id=o.user_id
11.1.1 实现方式一:使用ResultType

思路:

定义专门的pojo类作为输出类型,其中定义了sql查询结果集所有的字段。此方法较为简单,企业中使用普遍。

实现:

1、根据查询结果创建一个pojo类,用来存储返回的数据
package com.atSchool.Pojo;

import lombok.Getter;
import lombok.Setter;


@Getter
@Setter
public class OrderUser extends Order {
	private String uName;
	private String birthday;
	private String sex;
	private String address;

	public OrderUser() {
	}

	public OrderUser(Integer id, Integer userId, String number, String creatTime, String note, String uName,
			String birthday, String sex, String address) {
		super(id, userId, number, creatTime, note);
		this.uName = uName;
		this.birthday = birthday;
		this.sex = sex;
		this.address = address;
	}

	// 这里还需要将父类的信息加上,否则,遍历的时候,数据会不全
	@Override
	public String toString() {
		return "OrderUser [uName=" + uName + ", birthday=" + birthday + ", sex=" + sex + ", address=" + address
				+ ", toString()=" + super.toString() + "]";
	}
}
2、创建一个mapper





	
	
		
		
		
		
		
		
		
		
		
		
		
		
	

	
		SELECT o.id,o.user_id,o.number,o.createtime,o.note,u.username,u.birthday,u.sex,u.address
		FROM `orders` o LEFT JOIN `user` u ON u.id=o.user_id
	

注意:

    别忘了在SqlMapConfig.xml中添加相应的mapper。注意这里返回的类型,type中的类名都可以直接写类名,是因为在SqlMapConfig.xml中统一取别名了
3、编写Dao接口
package com.atSchool.Dao;

import java.util.List;

import com.atSchool.Pojo.OrderUser;


public interface OrderUserDao {
	List queryOrderUser();
}
4、开始测试
// 测试OrderUser中的查询
public static void teseForOrderUser() throws IOException {
    InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
    SqlSession openSession = new SqlSessionFactoryBuilder().build(resourceAsStream).openSession();
    OrderUserDao mapper = openSession.getMapper(OrderUserDao.class);
    List queryOrderUser = mapper.queryOrderUser();
    for (OrderUser orderUser : queryOrderUser) {
        System.out.println(orderUser);
    }
}

11.1.2 实现方式二:使用ResultMap

思路:

在Order类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息.

实现:

1、在Order类中加入User属性
package com.atSchool.Pojo;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;


@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Order {
	private User user;
	private Integer id;
	private Integer userId;
	private String number;
	private String creatTime;
	private String note;
}
2、使用resultMap标签中的association进行关联

    
    
    
    
    
    
    
    

    
        
        
        
        
        
    



		SELECT employeeNumber,lastName,firstName,reportsTo FROM `employees` 
		WHERe employeeNumber=#{id1}
	
	
	
    SELECT employeeNumber,lastName,firstName,reportsTo FROM `employees` 

在Dao接口中添加相应的方法

List queryEmployees();

开始使用

public static void teseForEmployees() throws IOException {
    InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
    SqlSession openSession = new SqlSessionFactoryBuilder().build(resourceAsStream).openSession();
    EmployeesDao mapper = openSession.getMapper(EmployeesDao.class);

    // 1、获取需要的页数和每页数据的条书
    // 正常应该是从页面获取到的数据的,这里就直接给出方便测试
    int pageNum = 1;
    int pageSize = 10;

    // 2、开启分页
    PageHelper.startPage(pageNum, pageSize);

    // 3、查询数据
    List queryEmployees = mapper.queryEmployees();

    // 4、将查询到的数据传给PageInfo
    PageInfo pageInfo = new PageInfo(queryEmployees);

    // 5、可以开始使用了
    System.out.println(pageInfo);	// 打印pageInfo,里面封装了很多分页的信息
    List list = pageInfo.getList();
    for (Object object : list) {
        System.out.println(object);
    }
}
4、PageInfo类里面的属性
属性说明
pageNum当前页
pageSize每页的数量
size当前页的数量
orderBy排序
startRow当前页面第一个元素在数据库中的行号
endRow当前页面最后一个元素在数据库中的行号
total总记录数
pages总页数
list结果集
prePage前一页
nextPage下一页
isFirstPage是否为第一页
isLastPage是否为最后一页
hasPreviousPage是否有前一页
hasNextPage是否有下一页
navigatePages导航页码数
navigatepageNums所有导航页号
navigateFirstPage导航第一页
navigateLastPage导航最后一页
firstPage第一页
lastPage最后一页
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/773275.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号