MyBatis学习

1、简介

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

2、写一个入门项目

思路流程:搭建环境–>导入Mybatis—>编写代码—>测试

2.1、搭建数据库

CREATE DATABASE `mybatis`;

USE `mybatis`;

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
`id` int(20) NOT NULL,
`name` varchar(30) DEFAULT NULL,
`pwd` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert  into `user`(`id`,`name`,`pwd`) values (1,'lxl','123456'),(2,'张三','abcdef'),(3,'李四','987654');

2.2、导入MyBatis相关jar 包

我们搭建完成数据库后在程序中首先就要导入mysql jar包、mybatis jar包以及junit jar包(直接使用maven导入较为方便)


   org.mybatis
   mybatis
   3.5.2


   mysql
   mysql-connector-java
   5.1.47


  junit
  junit
  3.8.1
  test

2.3、新建User类等准备工作

新建一个pojo用户类

public class User {
    private int id;
    private String name;
    private String pwd;
	//set get方法以及构造方法
}

创建mapper接口

package com.lxl.mapper;
import com.lxl.pojo.User;
import java.util.List;
public interface UserMapper {
	List selectUser();
}

创建mapper接口实现xml文件(原先是写UserMapperImpl)

namespace参数为USerMapper对应的接口,select id对应的是其方法名(selectUSer),resultType为返回类型,这里需要注意一下其中返回信息为List但在这里我们仍写User。




    
  

2.4、编写MyBatis配置文件

XML配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。在resource文件夹下新建mybatis-config.xml文件(名字为官方建议),其中包括连接数据库的一些配置。需要注意的是mysql版本对应的url连接方法有些许不同。然后在标签中注册userMapper.xml文件。




    
	    
		    
		    
			    
			    
			    
			    
		    
	    
    
    
    	
    

2.5、编写MyBatis工具类

此工具类的目的是使用sqlSessionFactory返回一个sqlSession对象,我们操作数据库是通过sqlSession对象进行操作的。其代码为写死的代码,一般无需改动。每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例。

package com.lxl.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;

public class MybatisUtils {

private static SqlSessionFactory sqlSessionFactory;

    static {
	    try {
		    String resource = "mybatis-config.xml";
		    InputStream inputStream = Resources.getResourceAsStream(resource);
		    sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		    } catch (IOException e) {
		    	e.printStackTrace();
		    }
    }
    
    //获取SqlSession连接
    public static SqlSession getSession(){
    	return sqlSessionFactory.openSession();
    }

}

2.6、编写测试类

现在我们一般使用代码块中的方法一进行操作。

package com.lxl.mapper;
import com.lxl.pojo.User;
import com.lxl.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class UserMapperTest {
    @Test
    public void selectUser() {
	    SqlSession session = MybatisUtils.getSession();
	    //方法一:
	    UserMapper mapper = session.getMapper(UserMapper.class);
	    List users = mapper.selectUser();
	    
	    //方法二:
	    //List users = session.selectList("com.kuang.mapper.UserMapper.selectUser");
	    
	    for (User user: users){
	    	System.out.println(user);
	    }
	    session.close();
    }
}

2.7、注意点

我们的userMapper.xml文件是写在了mapper包下,不在resources文件夹下,所以maven并不会将其进行编译到target对应的目录下,我们需要对pom.xml进行一些配置,让其能加载到target目录下。


    
	    
		    src/main/java
		    
			    **/*.properties
			    **/*.xml
		    
		    false
		    
		    
			    src/main/resources
			    
				    **/*.properties
				    **/*.xml
			    
			    false
	    
    

3、CRUD操作及配置

CRUD是指在做计算处理时的增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)几个单词的首字母简写。主要被用在描述软件系统中DataBase或者持久层的基本操作功能。

3.1、select

select语句有很多属性可以详细配置每一条SQL语句

1.SQL语句返回值类型。【完整的类名或者别名】
2.传入SQL语句的参数类型 。【万能的Map,可以多尝试使用】
3.命名空间中唯一的标识符。【namespace】
4.接口中的方法名与映射文件中的SQL语句ID 一一对应

在第二部分的入门项目中我们已经学到了如何使用MyBatis对mysql进行操作,与其类似,我们现在来学习一下额外的内容。

3.1.1根据id查询用户

1、在UserMapper中添加对应方法

public interface UserMapper {
   //查询全部用户
   List selectUser();
   //根据id查询用户
   User selectUserById(int id);
}

2、在UserMapper.xml中添加Select语句


3、测试类中测试

@Test
public void tsetSelectUserById() {
   SqlSession session = MybatisUtils.getSession();  //获取SqlSession连接
   UserMapper mapper = session.getMapper(UserMapper.class);
   User user = mapper.selectUserById(1);
   System.out.println(user);
   session.close();
}

3.1.2根据密码和名字查询用户

与使用id查询用户类似,只不过是现在参数有两个,有两种方法进行查询。

思路一:直接在方法中传递参数

1、在接口方法的参数前加 @Param属性
2、Sql语句编写的时候,直接取@Param中设置的值即可,不需要单独设置参数类型
//通过密码和名字查询用户
User selectUserByNP(@Param("username") String username,@Param("pwd") String pwd);

   

思路二:使用万能的Map

1、在接口方法中,参数直接传递Map;
User selectUserByNP2(Map map);
2、编写sql语句的时候,需要传递参数类型,参数类型为map

3、在使用方法的时候,Map的 key 为 sql中取的值即可,没有顺序要求!
Map map = new HashMap();
map.put("username","小明");
map.put("pwd","123456");
User user = mapper.selectUserByNP2(map);

如果参数过多,我们可以考虑直接使用Map实现,如果参数比较少,直接传递参数即可

注意点:
所有的增删改操作都需要提交事务!

接口所有的普通参数,尽量都写上@Param参数,尤其是多个参数时,必须写上!

有时候根据业务的需求,可以考虑使用map传递参数!

为了规范操作,在SQL的配置文件中,我们尽量将Parameter参数和resultType都写上!

insert、update、delete全部类似

4、ResultMap及分页

ResultMap

**问题:**mapper映射文件中select语句是相当于select id,name,pwd from user where id = #{id},mybatis会根据这些查询的列名(会将列名转化为小写,数据库不区分大小写),去对应的实体类中查找相应列名的set方法设值,如果对应属性值与数据库中的属性不一致,找不到对应的set方法 , 对应返回值就为null。


解决方案1、为列名指定别名,别名和java实体类的属性名一致


方案2:使用结果集映射->ResultMap 【推荐】


   
   
   
   
   



我们一般采用手动映射的方式在 select 标签中的resultMap中填写我们定义的map。如上述代码所示。当然也可以使用自动映射,直接写resultType=“map”,但只是简单地将所有的列映射到 HashMap 的键上,而HashMap 不是一个很好的模型。

分页

在学习mybatis等持久层框架的时候,会经常对数据进行增删改查操作,使用最多的是对数据库进行查询操作,如果查询大量数据的时候,我们往往使用分页进行查询,也就是每次处理小部分数据,这样对数据库压力就在可控范围内。

使用Limit实现分页

#语法
SELECT * FROM table LIMIT stratIndex,pageSize
主要实现其中的startIndex以及pageSize等参数通过函数传过来就行了

SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15  

#为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:   
SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.  

#如果只给定一个参数,它表示返回最大的记录行数目:   
SELECT * FROM table LIMIT 5; //检索前 5 个记录行  

#换句话说,LIMIT n 等价于 LIMIT 0,n。

RowBounds分页

我们除了使用Limit在SQL层面实现分页,也可以使用RowBounds在Java代码层面实现分页,当然此种方式作为了解即可。我们来看下如何实现的!
主要是在测试类等Java代码层面对其实现分页。

@Test
public void testUserByRowBounds() {
   SqlSession session = MybatisUtils.getSession();

   int currentPage = 2;  //第几页
   int pageSize = 2;  //每页显示几个
   RowBounds rowBounds = new RowBounds((currentPage-1)*pageSize,pageSize);

   //通过session.**方法进行传递rowBounds,[此种方式现在已经不推荐使用了]
   List users = session.selectList("com.kuang.mapper.UserMapper.getUserByRowBounds", null, rowBounds);

   for (User user: users){
   	System.out.println(user);
  }
   session.close();
}

日志

使用Mybatis是基于接口,配置文件的源代码执行过程。因此,我们必须选择日志工具来作为我们开发,调节程序的工具。具体使用现先不写在这里,后续可能会更新。

5、使用注解开发

mybatis最初配置信息是基于 XML ,映射语句(SQL)也是定义在 XML 中的。而到MyBatis 3提供了新的基于注解的配置。不幸的是,Java 注解的的表达力和灵活性十分有限。最强大的 MyBatis 映射并不能用注解来构建。利用注解开发就不需要mapper.xml映射文件了。使用注解和配置文件协同开发,才是MyBatis的最佳实践!

步骤1、我们在我们的接口中添加注解

//查询全部用户
@Select("select id,name,pwd password from user")
public List getAllUser();

2、在mybatis的核心配置文件中注入



   

3、测试

@Test
public void testGetAllUser() {
   SqlSession session = MybatisUtils.getSession();
   //本质上利用了jvm的动态代理机制
   UserMapper mapper = session.getMapper(UserMapper.class);

   List users = mapper.getAllUser();
   for (User user : users){
   	System.out.println(user);
  }

   session.close();
}

其他的步骤也都类似。而注解的本质是利用了jvm的动态代理机制

6、多对一以及一对多处理

多对一

多个学生对应一个老师,如果对于学生这边,就是一个多对一的现象,即从学生这边关联一个老师!
现在我们要查询学生表信息,但学生表里存放的只有对应老师的id而不是对应的老师这个对象。

数据表信息

CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师');

CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8


INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');

pojo用户信息

public class Student {
    private int id;
    private String name;
    //多个学生可以是同一个老师,即多对一
    private Teacher teacher;
}

public class Teacher {
    private int id;
    private String name;
}

设置mapper(StudentMapper、TeacherMapper)

public interface StudentMapper {
    //获取所有学生及对应老师的信息
    public List getStudents();//对应两个获取学生表的方法
    public List getStudents2();
}

设置对应mapper.xml

我们实现查询的方法一般有两个,分别是子查询和按照结果查询。

子查询

association对应这复杂属性映射



	



按照结果查询

一般来说按照结果查询更加方便一点。




    
    
    
    
        
    

测试

@Test
public void testGetStudents(){
    SqlSession session = MybatisUtils.getSession();
    StudentMapper mapper = session.getMapper(StudentMapper.class);

    List students = mapper.getStudents();

    for (Student student : students){
        System.out.println(
                "学生名:"+ student.getName()
                        +"\t老师:"+student.getTeacher().getName());
    }
    session.close();
}

@Test
public void testGetStudents2(){
    SqlSession session = MybatisUtils.getSession();
    StudentMapper mapper = session.getMapper(StudentMapper.class);

    List students = mapper.getStudents2();

    for (Student student : students){
        System.out.println(
                "学生名:"+ student.getName()
                        +"\t老师:"+student.getTeacher().getName());
    }
    session.close();
}

一对多

一个老师拥有多个学生,如果对于老师这边,就是一个一对多的现象,即从一个老师下面拥有一群学生(集合)!
若我们查询老师信息,同时想要获得所查询老师信息下的学生信息,这需要用到一对多的查询。与多对一类似,我们仍有两种方法查询,分别是按结果嵌套处理以及按查询嵌套处理。

编写实体类pojo

public class Student {
   private int id;
   private String name;
   private int tid;
}
public class Teacher {
   private int id;
   private String name;
   //一个老师多个学生
   private List students;
}

按结果嵌套处理

TeacherMapper接口编写方法

//获取指定老师,及老师下的所有学生
public Teacher getTeacher(int id);

编写接口对应的Mapper配置文件(按结果嵌套查询)



   
   

   
       
       
           
           
           
       
   

将Mapper文件注册到MyBatis-config文件中

测试

@Test
public void testGetTeacher(){
   SqlSession session = MybatisUtils.getSession();
   TeacherMapper mapper = session.getMapper(TeacherMapper.class);
   Teacher teacher = mapper.getTeacher(1);
   System.out.println(teacher.getName());
   System.out.println(teacher.getStudents());
}

按查询嵌套处理

对应接口对应的Mapper配置文件



   
   


总结:

1、关联-association

2、集合-collection

3、所以association是用于一对一和多对一,而collection是用于一对多的关系

4、JavaType和ofType都是用来指定对象类型的

其中JavaType是用来指定pojo中属性的类型
ofType指定的是映射到list集合属性中pojo的类型。

本博客是学习Spring的笔记记录,学习参考狂神说SSM框架系列:狂神说SSM框架系列

你可能感兴趣的:(SSM,mybatis,学习,java)