Mybatis学习笔记(持续更新中)

Atypora-root-url: img

一、mybatis初始配置

1、首先配置好maven环境,IDEA的setting等
在IDEA中创建一个Maven工程

new–project,–maven ,不选择任何,创建父工程

创建完成后 看一下setting中的maven设置是否正确

等待maven初始化完成后 删除Src

右键父目录new创建module,maven–

在这里插入图片描述

更改新module里面的pom.xml

缺少iml文件

在缺少.iml文件项目下运行mvn idea:module,完成后将自动生成.iml文件

2、在pom文件中添加mybaits起步依赖和sql驱动
  <!-- 添加mybatis组件-->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
<!--        添加mysql数据库驱动包-->
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.25</version>
        </dependency>
3、创建数据库脚本
CREATE DATABASE mydb;
CREATE TABLE admin(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(32) NOT NULL,
PASSWORD VARCHAR(32) NOT NULL,
age INT,
telephone VARCHAR(11)
);
INSERT INTO admin(NAME,PASSWORD,age,telephone)VALUES('ccc','000000',31,'12345678947');
INSERT INTO admin(NAME,PASSWORD,age,telephone)VALUES('ddd','000000',31,'12345678947');
INSERT INTO admin(NAME,PASSWORD,age,telephone)VALUES('bbb','000000',31,'12345678947');
COMMIT;
4、编写mybatis的配置文件

(src/main/resources/mybatis-config.xml)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--    envirorments表示mybatis的运行环境,这里mybatis可以定义多个环境-->
    <environments default="mysql">
        <environment id="mysql">
<!--            transactionManager表示事务管理器-->
            <transactionManager type="JDBC"/>
<!--            dataSource表示数据源-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mydb?useUnicode=true&amp;characterEncoding=UTF8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
 
</configuration>
5、编写实体对象

根据数据库表的字段来编写

public class Admin {
    private int id;
    private String name;
    private String password;
    private int age;
    private String telephone;

使用alt+insert键 自动生成 set和get方法 还有tostring方法

6、对于mybatis而言,一张数据库对应一个映射文件,映射文件主要编写的sql语句(AdminMapper.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">
<!--        namespace唯一性  表示命名空间,这里写成唯一的就行-->
<mapper namespace="com.woniuxy.mapper.AdminMapper">
    <select id="selectCount" resultType="int">
        select count(*) from admin
    </select>
</mapper>

编写完mapper文件之后,系统是找不到的,必须要在配置文件中进行注册,具体注册如下

mybatis-config.xml中

<mappers>
    <mapper resource="mapper/AdminMapper.xml"></mapper>
</mappers>
7、编写测试文件
package com.woniuxy;

import static org.junit.Assert.assertTrue;

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 org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
public class AppTest 
{

    @Test
    public void testMybatisQuickStart(){
        //获取配置文件,根据配置文件获取输入流
        InputStream in=null;
        try {
            in= Resources.getResourceAsStream("mybatis-config.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取SqlSessionFactory
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
        //通过SqlSessionFactory获取SqlSession对象
        SqlSession sqlSession=sqlSessionFactory.openSession();
        Object obj= sqlSession.selectOne("com.woniuxy.mapper.AdminMapper.selectCount");
        if (obj instanceof Integer){
            Integer count=(Integer) obj;
            System.out.println("查询的个数是"+count);
        }
        //关闭sqlsession
        sqlSession.close();
    }
}

8、mybatis工作原理

在这里插入图片描述

(1)读取MyBatis配置文件mybatis-config.xml, myoatis-config.xml作为MyBatis的全局配置文件,配置了MyBatis的运行环境等信息,其中主要内容是获取数据库连接.

(2)加载映射文件Mapper.xml。 Mapper.xml文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在myBatis-config.xml中加载才能执行,mybatis-config.xml可以加载多个配置文件,每个配置文件对应数据库中的一张表。

(3 )构建会话工厂。通过MyBatis的环境等配置信息构建会话工SqlSessionFactory.

(4 )创建SqlSession对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL的所有方法。

(5 ) MyBatis底层定义了一个Executor接口来操作数据库,它会根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。

(6)在Executor接口的执行方法中,包含一个 MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等。Mapper.xml这文件中一个SQL对应一个MappedStatement对象,SQL的id即是MappedStatement的id。

(7)输入参数映射。在执行方法时,MappedStatement对象会对用户执行SQL语句的输入参数进行定义(可以定义为Map、List类型、基本类型和POJO类型,Executor执行器会通过MappedStatement对象在执行SQL前,将输入的Java对象映射到SQL语句中。这里对输入参数的映射过程就类似于JDBC编程中对preparedStatement对象设置参数的过程.

(8)轮出结果映射。在数据库中执行完SQL语句后,,MappedStatement对象会对SQL执行输出的结果进行定义(可以定义为Mlap和List类型、基本类型、POJO类型)), Executor执行器会通过MappedStatement对象在执行SQL语句后,将输出结果映射至Java对象中。这种将输出结果映射到Java对象的过程就类似于JDBC编程中对结果的解析处理过程。

9、优化代码,编写MybatisUtil.java
package com.woniuxy.util;

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 MyBatisUtil {
    private static SqlSessionFactory factory;
    static {
        //获取配置文件,根据配置文件获取输入流
        InputStream in=null;
        try {
            in= Resources.getResourceAsStream("mybatis-config.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取SqlSessionFactory
        factory=new SqlSessionFactoryBuilder().build(in);
    }
    //获取Sqlsession对象
    public static SqlSession createSession(){
        return factory.openSession();
    }
    //关闭session的方法
    public static void closeSession(SqlSession sqlSession){
        if (sqlSession!=null){
            sqlSession.close();
        }
    }
}

测试

@Test
    public void testMybatisUtil(){
        SqlSession sqlSession = MyBatisUtil.createSession();
        Object obj=sqlSession.selectOne("com.woniuxy.mapper.AdminMapper.selectCount");
        if (obj instanceof Integer){
            Integer count=(Integer) obj;
            System.out.println("查询的个数是"+count);
        }
        MyBatisUtil.closeSession(sqlSession);
    }
}

二、Mybatis 核心对象

src/main/java/com/woniuxy/mapper/AdminMapper.java

package com.woniuxy.mapper;

public interface AdminMapper {
    public int getCount();
}

src/main/resources/mapper/AdminMapper.java

<?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名称就必须和src/main/java接口的名称必须一致-->
<mapper namespace="com.woniuxy.mapper.AdminMapper">
    <select id="selectCount" resultType="int">
        select count(*) from admin
    </select>
</mapper>

在这里插入图片描述

编写数据库文件datasource.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF8
username=root
password=123456

引入数据库文件

<configuration>
    <properties resource="datasource.properties"></properties>
    <!--    envirorments表示mybatis的运行环境,这里mybatis可以定义多个环境-->
    <environments default="mysql">
        <environment id="mysql">
            <!--            transactionManager表示事务管理器-->
            <transactionManager type="JDBC"/>
            <!--            dataSource表示数据源-->
            <dataSource type="POOLED">
<!--                <property name="driver" value="com.mysql.jdbc.Driver"/>-->
<!--                <property name="url" value="jdbc:mysql://localhost:3306/mydb?useUnicode=true&amp;characterEncoding=UTF8"/>-->
<!--                <property name="username" value="root"/>-->
<!--                <property name="password" value="123456"/>-->
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

三、日志记录

日志分类

1、业务日志

2、错误日志

(1)mybatis集成日志

这里用log4j为例

第一步,在pom.xml里添加组件

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

在resources中新建log4j.properties

log4j.rootLogger=DEBUG,stdout,fileAppender

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
#5p中的P代表级别    %m代表输出信息,%n代表换行

log4j.appender.fileAppender = org.apache.log4j.FileAppender
log4j.appender.fileAppender.File = E:/IDEA/log.log
# 日志输出地址
log4j.appender.fileAppender.Append = true
log4j.appender.fileAppender.Threshold = DEBUG

log4j.appender.fileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern = %-d{yyyy-MM-dd HH:MM:SS}  [%t:%r] - [%p] %m%n

在mabatis中的configuration下新建setting

<settings>
    <setting name="logImpl" value="LOG4J"/>
</settings>

测试类中

import static org.junit.Assert.assertTrue;

import com.woniuxy.mapper.AdminMapper;
import com.woniuxy.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

public class AppTest 
{
    private Logger logger = Logger.getLogger(getClass());
    @Test
    public void testOperSqlSessionWithInterface()
    {
        SqlSession sqlSession= MyBatisUtil.createSession();
        AdminMapper adminMapper=sqlSession.getMapper(AdminMapper.class);
        int count=adminMapper.getCount();
        logger.debug("共有"+count+"条数据");
        System.out.println("结果是"+count);
        MyBatisUtil.closeSession(sqlSession);
    }
}

安装插件 grep console setting–>plugins 对日志分类级别的颜色

插件设置 setting–>左侧底部有grep console

在这里插入图片描述

四、配置类型别名

AdminMapper.java
import com.woniuxy.pojo.Admin;

public interface AdminMapper {
    public int getCount();
    public Admin selectAdminById(int id);
}

AdminMapper.xml

<select id="selectAdminById" parameterType="java.lang.Integer" resultType="com.woniuxy.pojo.Admin">
    select * from admin where id=#{id}
</select>

apptest.java

@Test
public void testTypeAlias(){
    SqlSession sqlSession= MyBatisUtil.createSession();
    AdminMapper adminMapper=sqlSession.getMapper(AdminMapper.class);
    Admin admin=adminMapper.selectAdminById(1);
    logger.info(admin);
    MyBatisUtil.closeSession(sqlSession);
}

五、设置别名

<!--    resulType表示返回类型,这里面一定要写全名,而不要只写类名
如果你觉得类全名不好写太长,可以设置别名,在mybatis-config.xml文件中 <typeAliases>
    <typeAlias type="com.woniuxy.pojo.Admin" alias="Admin"></typeAlias>
</typeAliases>-->
<typeAliases><!--设置别名-->
<!--        <typeAlias type="com.woniuxy.pojo.Admin" alias="Admin"></typeAlias>-->
        <package name="com.woniuxy.pojo"/>
    </typeAliases>

alias定义的名字Admin 用admin也能搜索到

推荐 package方法名字不能随便叫,只能叫原来定义的名字

六、连接池

数据库连接池负责分配管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个

dataSource表示数据源type表示数据源类型
type的取值
pooled:使用连接池的数据源
unpooled:不使用连接池的数据源
JNDI:使用JNDI实现的数据源

mybatis内部定义了实现javax.sql.DataSource接口的UnpooledDataSource 、PooledDataSource类来定义UNPOOLED、Pooled类型的数据源

CTRL+N调出如下对话框进行搜索
在这里插入图片描述

七、LomBok学习

1、在pom.xml中添加依赖

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
</dependency>
<!--            编译和测试的时候有用-->

2、IDEA中安装lombok插件

在这里插入图片描述

重启IDEA后 右下角有个小窗口 点Enable
在这里插入图片描述

如果关闭了 在setting中进行设置

在这里插入图片描述

4、编写lombok窗口

在这里插入图片描述

5、使用lombok的注释声明

@Data生成setter、getter、equal、toString、hasCode、无参构造方法

@Setter 只生成setter方法

@getter只生成getter方法

@AllArgsConstructor生成全参的构造方法

在这里插入图片描述

日志台文件变色区分

在IDEA中打开Setting,选中Plugins,输入框里搜索
Grep-Console
点击下载并安装

八、Mybatis单表的增删改查CRUD

AdminMapper.xml 映射文件

<insert id="add" parameterType="admin">
        insert into admin(name,age,password,telephone)values (#{name},#{age},#{password},#{telephone})
    </insert>
    <delete id="delete" parameterType="int">
    delete from admin where id=#{id}
    </delete>
    <update id="update" parameterType="admin">
        update admin set name=#{name},password=#{password},age=#{age},telephone=#{telephone} where id=#{id}
    </update>
<!--    如果是list。resultType的值为该List集合中元素的类型-->
    <select id="findAll" resultType="admin">
        select * from admin
    </select>

Apptest.java 测试

private Logger logger = Logger.getLogger(AppTest.class);
@Test
 public void testAdd() {
    SqlSession sqlSession = MyBatisUtil.createSession();
    AdminMapper adminMapper=sqlSession.getMapper(AdminMapper.class);
    try {
        Admin admin=new Admin();
        admin.setName("mocc");
        admin.setAge(19);
        admin.setPassword("12345678");
        admin.setTelephone("13345546374");
        adminMapper.add(admin);
        sqlSession.commit();//提交
    } catch (Exception e) {
        sqlSession.rollback();//回滚
        e.printStackTrace();
    }
    MyBatisUtil.closeSession(sqlSession);
}
 @Test
 public void testdelete(){
     SqlSession sqlSession = MyBatisUtil.createSession();
     AdminMapper adminMapper=sqlSession.getMapper(AdminMapper.class);
     try {
         adminMapper.delete(5);
         sqlSession.commit();//提交   ctrl+alt+t 弹出try...catch窗口
     } catch (Exception e) {
         e.printStackTrace();
         sqlSession.rollback();
     }
     MyBatisUtil.closeSession(sqlSession);
 }
 @Test
 public void testupdate(){
     SqlSession sqlSession = MyBatisUtil.createSession();
     AdminMapper adminMapper=sqlSession.getMapper(AdminMapper.class);
     Admin admin=new Admin();
     admin.setId(5);
     admin.setName("mappp");
     admin.setAge(19);
     admin.setPassword("12345678");
     admin.setTelephone("13345546374");
     try {
         adminMapper.update(admin);
         sqlSession.commit();//提交
     } catch (Exception e) {
         e.printStackTrace();
         sqlSession.rollback();
     }
     MyBatisUtil.closeSession(sqlSession);
 }
 @Test
 public void testFindAll(){
     SqlSession sqlSession = MyBatisUtil.createSession();
     AdminMapper adminMapper=sqlSession.getMapper(AdminMapper.class);
     List<Admin> all= adminMapper.findAll();
     for (Admin admin:all){
         logger.info(admin);
     }
     MyBatisUtil.closeSession(sqlSession);
 }

AdminMapper.java 接口

public void add(Admin admin);
public void delete(int id);
public void update(Admin admin);
public List<Admin> findAll();

九、Mybatis参数处理

1、单参数处理

1)接口

package com.woniuxy.mapper;

import com.woniuxy.pojo.Admin;

public interface AdminMapper {
    public Admin selectAdminByName(String name);
}

2)映射文件

<mapper namespace="com.woniuxy.mapper.AdminMapper">
    <select id="selectAdminByName" resultType="admin" parameterType="string">
--    parameterType="java.lang.String"
        select * from admin where name=#{name}
    </select>
</mapper>

3)测试文件

private Logger logger = Logger.getLogger(this.getClass());
@Test
public void testSingleParam(){
    SqlSession sqlSession=MyBatisUtil.createSession();
    AdminMapper adminMapper= sqlSession.getMapper(AdminMapper.class);
    Admin admin=adminMapper.selectAdminByName("mocc");
    logger.info(admin);
    MyBatisUtil.closeSession(sqlSession);
}

4)观察控制台效果

在这里插入图片描述

通过控制台观察,输出的SQL语句使用了占位的方式,JDBC中如果要输入参数有两种方法

4.1)可以通过拼接SQL语句方式来完成
4.2)通过?占位的方式来完成

如果在mybatis中 使用了#{}的方式,他就是占位的方式

#{key} key的内容不是和接口中参数名称一致的,

这个key的内容,如果是单参数,mybatis限制的非常宽松,只要类型一样就可以,不管名字取成什么

2、多参数处理

2.1通过@Param方式来指定参数名称

1)接口

public interface AdminMapper {
    public Admin selectAdminByNameAndAge(String name,int age);
}

2)映射文件

<select id="selectAdminByNameAndAge" resultType="admin" >
    select * from admin where name like concat('%',#{name},'%') AND age>#{age}
</select>

3)测试代码

@Test
public void testMultiParaml(){
    SqlSession sqlSession=MyBatisUtil.createSession();
    AdminMapper adminMapper= sqlSession.getMapper(AdminMapper.class);
    Admin admin=adminMapper.selectAdminByNameAndAge("s",30);
    logger.info(admin);
    MyBatisUtil.closeSession(sqlSession);
}

测试观察控制台—报错

在这里插入图片描述
在这里插入图片描述

如果写的多个参数,这时候发现并没有找到

<!--    <select id="selectAdminByNameAndAge" resultType="admin" >-->
<!--        select * from admin where name like concat('%',#{arg0},'%') AND age>#{arg1}-->
<!--    </select>-->
    <select id="selectAdminByNameAndAge" resultType="admin" >
        select * from admin where name like concat('%',#{param1},'%') AND age>#{param2}
    </select>

Mybatis的规定,如果是多个参数,这个时候可以使用arg0,arg1,arg2,arg3,arg4…argn或者使用param1,param2…paramn

如上规定不灵活,如果程序员自己定义名称,需要通过@Param

2.2通过实体对象来传值

通过实体对象来传值,实际上#{key} key的值是和实体对象中的属性名要保持一致的

在这里插入图片描述

测试

@Test
public void testMultiParam2(){
    SqlSession sqlSession=MyBatisUtil.createSession();
    AdminMapper adminMapper= sqlSession.getMapper(AdminMapper.class);
    Admin entity = new Admin();
    entity.setName("b");
    entity.setAge(30);
   Admin admin=adminMapper.selectAdminByEntity(entity);
    logger.info(admin);
    MyBatisUtil.closeSession(sqlSession);
}

2.3通过Map集合来传值

接口

public interface AdminMapper {
    public Admin selectAdminByName(String name);
    //public Admin selectAdminByNameAndAge(String name,int age);
    public Admin selectAdminByNameAndAge(@Param("name")  String name,@Param("age") int age);
    public Admin selectAdminByEntity(Admin admin);
    public Admin selectAdminByMap(Map<String,Object> map);
}

AdminMapper.xml映射

<select id="selectAdminByMap" resultType="admin">
    select * from admin where name like concat('%',#{name},'%') AND age>#{age}
</select>

测试

@Test
public void testMultiParam3(){
    SqlSession sqlSession=MyBatisUtil.createSession();
    AdminMapper adminMapper= sqlSession.getMapper(AdminMapper.class);
    Map<String,Object> map=new HashMap<String,Object>();
    map.put("name","b");
    map.put("age",30);
    Admin admin=adminMapper.selectAdminByMap(map);
    logger.info(admin);
    MyBatisUtil.closeSession(sqlSession);
}

如果使用map作为参数的话,那么#{key} key的值是和map中的键是相同的这样就能绑定到一起了

如上三种方式处理多参数的传值问题,实际上底层都是map集合

这三种实际开发中都有用途。

一般参数不超过三个的请使用第一种,参数超过3种以上可以使用实体或者map对象

3、${}和#{}区别

#{}作为参数来传递数据的,通过控制台观察,我们发现,如果使用#{} 这种操作,相当于JDBC中预处理,使用?来进行站位,如果使用 , 相 当 于 J D B C 中 的 S t a t e m e n t 原 生 J D B C 不 支 持 占 位 符 的 地 方 就 要 使 用 {},相当于JDBC中的Statement 原生JDBC不支持占位符的地方就要使用 JDBCStatementJDBC使{}进行取值,

#{}这就是JDBC中的预处理操作,PreparedStatement来完成预处理语句的执行操作,在预处理操作中使用?来占位,后续再赋值

${}这种方式是JDBC中的拼接方式(字符串)来完成的,

在使用${}完成查询的过程中,需要注意的就是必须要在接口方法中参数前面带@Param(不管是一个参数还是多个参数)

在使用${}过程中会出现SQL注入,安全性低,使用#{}不会出现这个问题(例子 Sm’Th ‘Sm’Th’ 前两个单引号形成闭合)

两种方法都可以使用的情况下,尽量使用#{}

1)例如排序不支持占位就不能使用#{},只能使用${}

2)例如在分表操作中就不能使用#{},只能使用${}

3)${}也可以完成#{}相同的功能,进行参数传递,只不过它需要外面带单引号

注意:${}可能会引发SQL注入,#{}不会

先写pojo普通Java类,再写接口类,再写xml SQL语句,然后在resources把XXX-config文件中的mappers目录地址写进去

4、返回结果

(1)、返回单个结果

<select id="selectStudentBysno" resultType="com.woniuxy.pojo.Student" parameterType="int">
    select * from student where sno=#{sno}
</select>

resultType填写类名或者类别名

返回值:表名(键=值,键=值)

在这里插入图片描述

(2)、返回List集合

<select id="selectStudents" resultType="com.woniuxy.pojo.Student">
    select * from student
</select>

resultType填写类名或别名,没有进行传参

如果返回值类型是List类型,那么在映射配置文件中节点中的resultType的属性值是这个List集合中的元素类型

public List<Student> selectStudents();
public void testselectStudents()
{
    SqlSession sqlSession = MyBatisUtil.createSession();
    StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
    List<Student> students =studentMapper.selectStudents();
    for (Student student:students){
        logger.info(student);
    }

    MyBatisUtil.closeSession(sqlSession);
}

(3)、返回Map

3.1返回Map类型的单个对象

接口、xml SQL语句、测试语句

public Map<String,Object> selectStudentno(@Param("sno") int sno);
  <select id="selectStudentno" parameterType="int" resultType="java.util.Map">
    select * from student where sno=#{sno}
</select>
@Test
public void testsselectStudentno()
{
    SqlSession sqlSession = MyBatisUtil.createSession();
    StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
    Map map=studentMapper.selectStudentno(2007010118);
    logger.info(map);
    MyBatisUtil.closeSession(sqlSession);
}

map返回值,{键=值,键=值} 逗号分割

在这里插入图片描述

3.2返回多条记录以Map类型作为返回值

接口

@MapKey("sname")
public Map selectStudentSnameLike(@Param("sname") String sname);

映射文件

  <select id="selectStudentSnameLike" parameterType="String" resultType="com.woniuxy.pojo.Student">
    select * from student where sname like concat(#{sname},'%')
</select>

测试

@Test
public void testselectStudentSnameLike()
{
    SqlSession sqlSession = MyBatisUtil.createSession();
    StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
    Map<String,Student> map=studentMapper.selectStudentSnameLike("刘");
        logger.info(map);
    MyBatisUtil.closeSession(sqlSession);
}

5、数据库字段和实体不一致的解决方法

(1)、使用AS来取别名

在这里插入图片描述

(2)、通过在mybatis的配置文件中设置驼峰命名来完成

①如果你的项目采用驼峰命名法,那么可以在mybatis-config.xml文件中进行设置
<settings>          
    <setting name="mapUnderscoreToCamelCase" value="true" /> </settings>  
②数据库字段和属性person_id=========>personId
③通过resultMap的方式完成(推荐使用)

在这里插入图片描述

6、类的关联关系

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(1)关联关系的分类

①一对一关联

例: 一人一身份证,一个身份证对应一个人

包装类方式(了解)

数据库表

#身份证表
create table tb_card(cid int primary key auto_increment,code varchar(18))
#测试数据
INSERT INTO tb_card(CODE)VALUES('370304199910101234');
#公民表
CREATE TABLE tb_person(pin int primary key auto_increment,
											 name varchar(50),
												age int,
												sex varchar(20),
												idcard int UNIQUE,
												FOREIGN KEY(idcard) REFERENCES tb_card(cid))
#测试数据
insert into tb_person(name,age,sex,idcard)VALUES('张三',32,'男',1)

创建实体类对象

@Data
public class Card {
    private int cid;
    private String code;
}
@Data
public class Person {
    private int pid ;
    private String name;
    private int age;
    private String sex;
    private Card card;
}
@Data
public class PersonCard extends Person {
    private String code;
}

mapper

public interface PersonMapper {
    public List<PersonCard> findAll();
}

映射文件

<resultMap id="personMap" type="PersonCard">
  <id column="pid" property="pid"></id>
  <result column="name" property="name"></result>
    <result column="age" property="age"></result>
    <result column="sex" property="sex"></result>
    <result column="code" property="code"></result>
</resultMap>
<select id="findAll" resultMap="personMap" >
    SELECT p.*,c.code from tb_person as p INNER JOIN tb_card c on p.idcard=c.cid
</select>

测试类

@Test
public void test1()
{
    SqlSession sqlSession= MyBatisUtil.createSession();
    PersonMapper personMapper= sqlSession.getMapper(PersonMapper.class);
    List<PersonCard> all= personMapper.findAll();
    for (PersonCard p:all){
        logger.info(p.getName()+"-->"+p.getCode());
    }
    MyBatisUtil.closeSession(sqlSession);
}
resultMap方式

创建实体类对象

package com.woniuxy.pojo;

import lombok.Data;

@Data
public class Card {
    private int cid;
    private String code;
}
package com.woniuxy.pojo;

import lombok.Data;

@Data
public class Person {
    private int pid ;
    private String name;
    private int age;
    private String sex;
    private Card card;//关联对象
}

mapper

package com.woniuxy.mapper;

import com.woniuxy.pojo.Person;

import java.util.List;

public interface PersonMapper {
    public List<Person> SelectAllPerson();

}

映射文件

<?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名称就必须和src/main/java接口的名称必须一致-->
<mapper namespace="com.woniuxy.mapper.PersonMapper">
    <resultMap id="personMap" type="person">
       <id column="pid" property="pid"></id>
       <result column="name" property="name"></result>
        <result column="age" property="age"></result>
        <result column="sex" property="sex"></result>
        <result column="cid" property="card.cid"></result>
        <result column="code" property="card.code"></result>
    </resultMap>
    <select id="SelectAllPerson" resultMap="personMap" >
        SELECT p.*,c.* from tb_person as p INNER JOIN tb_card c on p.idcard=c.cid
    </select>

</mapper>

测试类

private Logger logger=Logger.getLogger(this.getClass());
@Test
public void TestSelectAllPerson()
{
    SqlSession sqlSession = MyBatisUtil.createSession();
    PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
    List<Person> all = personMapper.SelectAllPerson();
    for (Person p:all){
        logger.info(p.getName()+"\t"+p.getSex()+"\t"+p.getCard().getCode());
    }
    MyBatisUtil.closeSession(sqlSession);
}
association嵌套映射
<?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名称就必须和src/main/java接口的名称必须一致-->
<mapper namespace="com.woniuxy.mapper.PersonMapper">
    <resultMap id="personMap" type="person">
       <id column="pid" property="pid"></id>
       <result column="name" property="name"></result>
        <result column="age" property="age"></result>
        <result column="sex" property="sex"></result>
    <!-- association:一对多的节点属性  常用属性如下
        property关联对象的名称
        javaType关联对象的类型(类全名,别名)
    -->
        <association property="card" javaType="card">
            <id property="cid" column="cid"></id>
            <result property="code" column="code"></result>
        </association>
    </resultMap>

    <select id="selectAllPerson" resultMap="personMap" >
        SELECT p.*,c.* from tb_person as p INNER JOIN tb_card c on p.idcard=c.cid
    </select>

</mapper>

测试

private Logger logger = Logger.getLogger(this.getClass());
@Test
public void shouldAnswerWithTrue()
{
    SqlSession sqlSession = MyBatisUtil.createSession();
    PersonMapper personMapper=sqlSession.getMapper(PersonMapper.class);
    List<Person> all =personMapper.selectAllPerson();
    for(Person p:all)
    {
        logger.info(p.getName()+"\t"+p.getSex()+"\t"+p.getCard().getCode());
    }
    MyBatisUtil.closeSession(sqlSession);
}
association分步查询
public interface CardMapper {
    public Card selectCardByCidWithStep(@Param("cid") int cid);
}
public interface PersonMapper {
    public List<Person> selectAllPerson();
}
<mapper namespace="com.woniuxy.mapper.CardMapper">
<select id="selectCardByCidWithStep"  parameterType="int" resultType="card">
    select * from tb_card where  cid=#{cid}
</select>
</mapper>
<mapper namespace="com.woniuxy.mapper.PersonMapper">
    <resultMap id="personMap" type="person">
       <id column="pid" property="pid"></id>
       <result column="name" property="name"></result>
        <result column="age" property="age"></result>
        <result column="sex" property="sex"></result>
    <!-- association:一对多的节点属性  常用属性如下
        property关联对象的名称
        javaType关联对象的类型(类全名,别名)
        select 分布查询的方法
        column:外键的值
    -->
        <association property="card" javaType="card" select="com.woniuxy.mapper.CardMapper.selectCardByCidWithStep" column="idcard">
            <id property="cid" column="cid"></id>
            <result property="code" column="code"></result>
        </association>
    </resultMap>

    <select id="selectAllPerson" resultMap="personMap" >
        SELECT p.*,c.* from tb_person as p INNER JOIN tb_card c on p.idcard=c.cid
    </select>
</mapper>
private Logger logger = Logger.getLogger(this.getClass());
@Test
public void shouldAnswerWithTrue()
{
    SqlSession sqlSession = MyBatisUtil.createSession();
    PersonMapper personMapper=sqlSession.getMapper(PersonMapper.class);
    List<Person> all =personMapper.selectAllPerson();
    for(Person p:all)
    {
        logger.info(p.getName()+"\t"+p.getSex()+"\t"+p.getCard().getCode());
    }
    MyBatisUtil.closeSession(sqlSession);
}

在这里插入图片描述

1+n次

分布查询的延迟加载

什么是延迟加载︰俗称懒加载(Lazy )︰需要的才去查询的这种情况。
为什么需要延迟加载:为了提高性能,把需要的信息不立即查出来,需要的时候再查。
如下操作虽然我只是需要人员本身信息,控制台也输出本身自己的信息,但是我们观察SQL语句,大家会发现,依然做的是立即加载

第一种方法:设置mybatis-config.xml
<settings>
    <!--       lazyLoadingEnabled 设置全局延迟加载,默认false表示没有开启延迟加载,这里设置为true表示延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
    <!--        设置按需加载-->
        <setting name="aggressiveLazyLoading" value="false"/>
</settings>
第二种方法:通过在association中设置fetchType的值来设置延迟加载(局部)
<association property="card"
             javaType="card"
             select="com.woniuxy.mapper.CardMapper.selectCardByCidWithStep"
             column="idcard"
             fetchType="lazy">
    <!--lazy延迟加载eager立即加载-->
    <id property="cid" column="cid"></id>
    <result property="code" column="code"></result>
</association>
②一对多关联

例:一个区对应多个街道

③多对多关联

一个老师对应多个学生,一个学生对应多个老师

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值