SSM-Mybatis(一)单表CURD

文章目录

第1章 SSM的学习路线

第一部分:mybatis(3阶段)

第二部分:spring(4阶段)

第三部分:springmvc(3阶段)

第2章 Mabatis阶段介绍

第一阶段:mybatis的入门+mybatis的基本操作

​ mybatis环境搭建(xml)

​ * 操作数据库CRUD的实现

​ * mybaits中的参数和结果集封装

​ * 分析mybatis中两种dao的编写方式

​ * 面向接口(推荐)

​ * 使用API面向实现类(不推荐)

第二阶段:mybatis深入

​ 连接池的深入

​ 动态sql语句的深入

​ 表关系的深入(一对多,多对多) 特殊:多对一/一对一

第三阶段:mybatis中的加载策略和缓存以及基于注解的mybatis开发

​ 加载策略(立即加载/延迟加载)

​ 缓存(一级缓存/二级缓存)

​ 注解开发Mybatis

本阶段目标
1:能够了解什么是框架(第3章)

2:掌握Mybatis框架开发快速入门(第4章)

3:掌握Mybatis框架的基本CRUD操作(代理)(第5章)

4:掌握Mybatis的参数深入(第6章)

5:掌握Mybatis的DAO层实现类开发(了解)(第7章)

第3章 Mybatis的概述

3.1 什么是Mybatis

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
当前,最新版本是MyBatis 3.5.2 ,其发布时间是2019年7月15日。

Mybatis(Hibernate)就是一个持久层的的框架。对JDBC做了轻量级封装。

3.2 什么是框架

3.2.1 什么是框架

JavaEE开发是分层的:表现层 业务层 持久层

SSM-Mybatis(一)单表CURD

常见的JavaEE 开发框架

1)解决数据的持久化问题的框架

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)

作为持久层的框架,还有一个封装程度更高的框架就是 Hibernate,但这个框架因为各种原因目前在国内的流行程度下降太多,现在公司开发也越来越少使用。 目前使用 Spring Data 来实现数据持久化也是一种趋势

2)解决 WEB层问题的 MVC 框架

**Spring MVC**属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。

Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。

使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架,如Struts1(现在一般不用),Struts2等。

3)解决技术整合问题的框架

**Spring**是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。

Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full**-stack**(一站式) 轻量级开源框架。

目的:解决企业应用开发的复杂性

功能:使用基本的JavaBean代替EJB

范围:任何Java应用

Spring是一个轻量级控制反转(IOC)和面向切面(AOP)的容器框架
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。

简而言之,框架其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。简单说就是使用别人搭好的舞台,你来做表演。而且,框架一般是成熟的,不断升级的软件。

3.2.2 mybatis框架

​ 明确:它是一个持久层框架,解决项目对数据库的CRUD操作,只要会方法名、sql语句,学mybatis框架很轻松。

3.2.3 持久层技术

回顾JDBC操作数据库
代码和缺点:见另外一篇博客 JDBC操作数据库

3.2.4 mybatis概述

​它是基于Java编写的持久层框架,使开发者不必关心传统jdbc的api,只关心sql语句本身。

mybatis 通过 xml或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中 sql的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。

为了我们能够更好掌握框架运行的内部过程,并且有更好的体验,下面我们将从自定义 Mybatis 框架开始来学习框架。此时我们将会体验框架从无到有的过程体验,也能够很好的综合前面阶段所学的基础。

什么是ORM?

	ORM :Object Relational Mapping	对象关系映射(目的:操作对象,就可以操作数据库)

	通过建立数据库表和Java实体类的对应关系,从而实现操作实体类就相当于操作数据库表。

​ ORM思想对应的框架有:mybatis(半自动),hibernate(全自动),spring data jpa(全自动,底层封装的就是hibernate)

现阶段的数据访问层框架:
SSM-Mybatis(一)单表CURD

第4章 Mybatis框架入门

4.1 创建Maven工程并引入相关坐标

创建项目mybaits_day01_quick

1.检查JDK环境
SSM-Mybatis(一)单表CURD
2.检查Tomcat环境(忽略,springmvc用到)

3.检查maven环境
SSM-Mybatis(一)单表CURD

4.2 导入Maven依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itheima</groupId>
    <artifactId>mybatis_day01_quick</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.18</version>
        </dependency>
        <!-- 日志坐标 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
    </dependencies>
</project>

4.3 创建数据库

创建数据库

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
  `id` int(11) NOT NULL auto_increment,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` datetime default NULL COMMENT '生日',
  `sex` char(1) default NULL COMMENT '性别',
  `address` varchar(256) default NULL COMMENT '地址',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

导入数据

insert  into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (41,'老王','2018-02-27 17:47:08','男','北京'),(42,'小二王','2018-03-02 15:09:37','女','北京金燕龙'),(43,'小二王','2018-03-04 11:34:34','女','北京金燕龙'),(45,'小猪佩琪','2018-03-04 12:04:06','男','北京金燕龙'),(46,'老王','2018-03-07 17:37:26','男','北京'),(48,'小马宝莉','2018-03-08 11:44:00','女','北京修正');

4.4创建实体类

创建包:cn.iyhome.domain

创建类:User.java

public class User implements Serializable {
    private int id;// 主键ID
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", sex='" + sex + '\'' +
                ", birthday=" + birthday +
                ", address='" + address + '\'' +
                '}';
    }
}

4.5 创建接口UserDao.java

创建接口,UserDao.java,用来操作数据库

创建包cn.iyhome.dao,创建接口IUserDao.java

public interface IUserDao {
    /**
     * 查询所有
     */
    List<User> findAll();
}

也有人将它命名UserMapper,这个是因人而异,我们为了大家的编程习惯,叫做Dao。

4.6 创建sqlMapConfig.xml

在resources包下,新建sqlMapConfig.xml,表示mybatis的配置文件
为了更好将数据库连接信息抽取出来,我们原来在C3P0连接池中也已经将数据库连接信息抽取出来,我们现在也一样将数据库的连接信息抽取出来,放到一个xml(SqlMapConfig.xml)文件中,后面再去对此配置文件进行xml解析,这样就可以将配置文件中的信息读取出来,以便在jdbc代码中直接使用这些数据库连接信息

<?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>
    <!--配置mybatis环境-->
    <environments default="mysql">
        <environment id="mysql">
            <!--配置事务管理-->
            <transactionManager type="JDBC"/>
            <!--配置数据源-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatisblog"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--配置映射文件信息-->
    <mappers>
        <mapper resource="cn/iyhome/dao/IUerDao.xml"/>
    </mappers>
</configuration>

4.7 创建UserDao.xml

因为是maven项目,所有xml的文件应该放在resources下,创建包com.itheima.dao,创建UserDao.xml,表示mybatis的映射文件(Dao有几个,映射文件就有几个)

<?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.iyhome.dao.IUserDao">
    <!--查找所有-->
    <select id="findAll" resultType="cn.iyhome.domain.User">
        select * from user
    </select>
</mapper>

4.8 创建测试类

在test文件夹下,创建包con.iyhome.test,创建类MyBatisTest.java

public class MyBatisTest {
    /**
     * 测试mybatis的环境搭建
     */
    public static void main(String[] args) throws IOException {
        //读取配置文件
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //构建SqlSessionFactory
        SqlSessionFactoryBuilder ssFacBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory ssFac = ssFacBuilder.build(is);
        //使用工程创建SqlSession
        SqlSession sqlSession = ssFac.openSession();
        //使用SqlSession构建Dao的代理对象
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        //执行Dao的findAll方法
        List<User> users = userDao.findAll();
        //遍历
        for (User user : users) {
            System.out.println(user);
        }
        //关闭资源
        sqlSession.close();
        is.close();
    }
}

查看测试结果
SSM-Mybatis(一)单表CURD

4.9 使用注解代替UserDao.xml

需要修改两个地方:
1.SqlMapConfig.xml
2.IUserDao.java

<!--配置映射文件信息-->
    <mappers>
        <!--<mapper resource="cn/iyhome/dao/IUerDao.xml"/>-->
        <!--如果是使用注解的话,此处应该是用class属性指定被注解的dao全限定类名-->
        <mapper class="cn.iyhome.dao.IUserDao"/>
    </mappers>
public interface IUserDao {
    /**
     * 查询所有
     */
    @Select("select * from user")
    List<User> findAll();
}

测试结果
SSM-Mybatis(一)单表CURD总结:Mybatis操作数据库对比往常,无非多了两个配置文件以及使用代理执行Dao中方法.

SqlMapConfig.xml ->配置mybatis环境,事务管理,数据源,配置映射文件信息(IUserDao.xml)
IUserDao.xml     ->映射对应的Dao接口和方法,要执行的sql语句,返回的结果集
test.java        ->使用SqlSessionFactory构建SqlSession对象,再构建代理对象执行操作数据库的方法

第5章 Mabatis的CRUD(操作接口)(掌握)

需求:实现查询所有的用户操作

5.1 查询所有

已经完成(略)

5.2 保存

需要涉及添加代码的文件
1.IUserDao.java
2.IUserDao.xml
3.添加日志log4j(非必须),此处添加是为了显示save()操作出现的问题

先恢复SqlMapConfig.xml代码,使用xml配置文件的方式,注解的方法后面再讲

	<!--配置映射文件信息-->
    <mappers>
        <mapper resource="cn/iyhome/dao/IUerDao.xml"/>
        <!--如果是使用注解的话,此处应该是用class属性指定被注解的dao全限定类名-->
        <!--<mapper class="cn.iyhome.dao.IUserDao"/>-->
    </mappers>

在IUserDao.java中添加方法

	/**
     * 保存用户
     */
    void saveUser(User user);

修改IUserDao.xml

<mapper namespace="cn.iyhome.dao.IUserDao">
    <!--查找所有-->
    <select id="findAll" resultType="cn.iyhome.domain.User">
        select * from user
    </select>

    <!--保存用户-->
    <insert id="saveUser" parameterType="cn.iyhome.domain.User">
        insert into user values(${username},${birthday},${sex},${address})
    </insert>
</mapper>

我们可以发现,这个sql语句中使用#{}字符,#{}代表占位符,我们可以理解是原来jdbc所学的?,它们都是代表占位符, 具体的值是由User类的username属性来决定的。使用OGNL表达式

parameterType属性:代表参数的类型,因为我们要传入的是一个类的对象,所以类型就写类的全名称。

注意:
这种方式要求,同时还要求 select,insert,delete,update这些标签中的id属性一定与代理接口中的方法名相同。

编写测试类
为了不写重复代码,我们先将测试类中的部分代码提取到方法中,然后编写测试方法

public class MybatisTest {
    InputStream is;
    SqlSessionFactoryBuilder ssFacBuilder;
    SqlSessionFactory ssFac;
    SqlSession sqlSession;

    @Before
    public void init() throws IOException {
        //读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //构建SqlSessionFactory
        ssFacBuilder = new SqlSessionFactoryBuilder();
        ssFac = ssFacBuilder.build(is);
        //使用工程创建SqlSession
        sqlSession = ssFac.openSession();
    }

    @After
    public void release() {
        //关闭资源
        sqlSession.close();
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Test
    public void findAll() {

        //使用SqlSession构建Dao的代理对象
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        //执行Dao的findAll方法
        List<User> users = userDao.findAll();
        //遍历
        for (User user : users) {
            System.out.println(user);
        }

    }

    @Test
    public void saveUser() {
        User user = new User();
        user.setAddress("中国西安");
        user.setUsername("海哥");
        user.setBirthday(new Date());
        user.setSex("男");

        //使用SqlSession构建Dao的代理对象
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        userDao.saveUser(user);
    }
}

运行测试类,控制台没有报错,但是查询数据库user表,并没有插入新数据,这是为什么?
我们来添加log4j日志文件查看原因
a.在pom.xml中添加坐标

		<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

ps:坐标是否添加成功,可以看此处
SSM-Mybatis(一)单表CURD
b.在resources文件下创建log4j.properties

# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:/axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

再次运行测试类,观察控制台输出,操作被回滚了. SSM-Mybatis(一)单表CURD解决方案:手动提交事务,在测试类中提交事务

	@After
    public void release() {
        //提交事务
        sqlSession.commit();
        //关闭资源
        sqlSession.close();
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

再次运行测试类,可以再控制台看到事务已经提交了,并且在数据库中查看数据也已经插入成功了.
SSM-Mybatis(一)单表CURDSSM-Mybatis(一)单表CURD
但其实还是有一个小问题,我们来看.
修改测试代码,然后运行测试类

	@Test
    public void saveUser() {
        User user = new User();
        user.setAddress("中国西安");
        user.setUsername("海哥");
        user.setBirthday(new Date());
        user.setSex("男");
        System.out.println("保存操作之前:"+user);
        //使用SqlSession构建Dao的代理对象
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        userDao.saveUser(user);
        System.out.println("保存操作之后:"+user);
    }

看控制台的输出,这时候发现保存操作之前User对象的id和保存操作之后User对象的id都为null,如果我们想在保存之后获取User对象的id呢?
SSM-Mybatis(一)单表CURD问题扩展:新增用户id的返回值
新增用户后,同时还要返回当前新增用户的id值,因为id是由数据库的自动增长来实现的,所以就相当于我们要在新增后将自动增长auto_increment的值返回。

Mysql自增主键的返回,语句如下:

insert into user(username,address,sex,birthday) values('张三','深圳','女','2018-07-24');
select last_insert_id()

修改IUserDao.xml

<!--保存用户-->
    <insert id="saveUser" parameterType="cn.iyhome.domain.User">
        <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
            select last_insert_id()
        </selectKey>
        insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})
    </insert>

查看
SSM-Mybatis(一)单表CURD

5.3 修改用户信息

需要涉及添加代码的文件
1.IUserDao.java
2.IUserDao.xml

修改IUserDao.java

	/**
     * 修改用户信息
     */
    void updateUser(User user);

修改IUserDao.xml

<!--修改用户-->
    <update id="updateUser" parameterType="cn.iyhome.domain.User">
        update user set sex=#{sex} where id=#{id}
    </update>

编写测试类

@Test
    public void updateUser() {
        User user = new User();
        user.setSex("女");
        user.setId(55);
        //使用SqlSession构建Dao的代理对象
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        userDao.updateUser(user);
    }

查看结果
SSM-Mybatis(一)单表CURD

5.4 删除用户

需要涉及添加代码的文件
1.IUserDao.java
2.IUserDao.xml

修改IUserDao.java

	/**
     * 删除用户
     */
    void deleteUser(Integer id);

修改IUserDao.xml

	<!--删除用户-->
    <delete id="deleteUser" parameterType="int">
        delete from user where id = #{id}
    </delete>

其中的#{uid}是占位符,代表参数的值由方法的参数传入进来的。

注意:

1.此处的#{uid}中的id其实只是一个形参,所以它的名称是*定义的,比如定义成#{abc}也是可以的。

2.关于parameterType的取值问题,对于基本类型我们可以直接写成int,short,double……也可以写成java.lang.Integer。

3.字符串可以写成string,也可以写成java.lang.String

也就是说:int是java.lang.Integer的别名

​ string是java.lang.String的别名

别名是不区分大小写

编写测试类

@Test
    public void deleteUser() {
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        userDao.deleteUser(42);
    }

查看结果:
SSM-Mybatis(一)单表CURD

5.5 主键查询

需要涉及添加代码的文件
1.IUserDao.java
2.IUserDao.xml

修改IUserDao.java

/**
 * 根据id查询用户信息
 * @param id
 * @return
 */
User findById(Integer id);

修改IUserDao.xml

<!-- 根据id查询用户 -->
<select id="findById" parameterType="INT" resultType="cn.iyhome.domain.User">
    select * from user where id = #{uid}
</select>

编写测试类

/**
 * 测试主键ID查询操作
 */
@Test
public void testFindOne(){
    //5.执行查询一个方法
    User  user = userDao.findById(50);
    System.out.println(user);
}

5.6 模糊查询

需要涉及添加代码的文件
1.IUserDao.java
2.IUserDao.xml

修改IUserDao.java

/**
 * 根据名称模糊查询用户信息
 * @param name
 * @return
 */
List<User> findByName(String name);

修改IUserDao.xml

<!-- 根据名称模糊查询 -->
<select id="findByName" parameterType="string" resultType="com.itheima.domain.User">
    select * from user where username like #{name}
</select>

编写测试类

/**
 * 测试主键ID查询操作
 */
@Test
@Test
public void testFindByName(){
    //5.执行查询一个方法
    List<User> users = userDao.findByName("%王%");
    for(User user : users){
        System.out.println(user);
    }
}

问题扩展 模糊查询的另一种配置方式

修改IUserDao.xml中的sql语句:

select * from user where username like '%${value}%'

注:我们在上面将原来的#{}占位符,改成了${value}。注意如果用模糊查询的这种写法,那么${value}的写法就是固定的,不能写成其它名字。

修改测试方法:

@Test
    public void testFindByName(){
        //5.执行查询一个方法
		//List<User> users = userDao.findByName("%王%");
        List<User> users = userDao.findByName("王");
        for(User user : users){
            System.out.println(user);
        }
    }

#{}和${}的区别

  • #{}表示一个占位符号
通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。 
  • ${}表示拼接sql串
通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。

那么为什么一定要写成${value}呢?我们一起来看TextSqlNode类的源码:
SSM-Mybatis(一)单表CURD
这就说明了源码中指定了读取的key的名字就是”value”,所以我们在绑定参数时就只能叫value的名字了。

第6章 Mybatis的参数深入

1:Mybatis的映射文件其实就是与DAO相对应,因为DAO中的方法有输入参数及返回结果,那么在Mybatis的映射文件中自然也就有与之对应的参数和返回结果。

2:在Mybatis的映射文件中参数用parameterType来代表,它的值可以是基本类型,也可以是包装的对象,这一点我们第二天学习中就使用过。

3:在Mybatis的映射文件中返回结果用resultTyperesultMap来代表。

resultType:当查询字段和封装实体的属性名称一致的情况下

resultMap:当查询字段和封装实体的属性名称不一致的情况下

6.1 了解OGNL

OGNL表达式:

	Object Graphic Navigation Language

	对象	  图	      导航	   语言

​ 它是通过对象的取值方法来获取数据。在写法上把get给省略了。

​ 比如:我们获取用户的名称

  • 类中的写法:user.getUsername();

  • OGNL表达式写法:user.username

​ mybatis中为什么能直接写username,而不用user.呢:

  • 因为在parameterType中已经提供了属性所属的类,所以此时不需要写对象名

Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo(Plain Ordinary Java Object)属性名称。

6.2 Mybatis的参数

6.2.1 parameterType(输入类型)

  • 传递简单类型 (略)

    int – int 或者 java.lang.Integer

    String – string 或者java.lang.String

    别名不区分大小写。

  • 传递pojo对象

    com.itheima.domain.User-- username、address、sex、birthday、id

6.2.2 QueryVo.java

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

Pojo类中包含pojo。

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

需要涉及添加代码的文件
1.添加QueryVO.java
2.IUserDao.java
3.IUserDao.xml

添加QueryVo.java

public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

修改IUserDao.java

	/**
     * 查询用户信息byQueryVo
     */
    void findUserByQueryVO();

修改IUserDao.xml

	<!--查找用户byQueryVo-->
    <select id="findUserByQueryVO" parameterType="cn.iyhome.domain.QueryVo" resultType="cn.iyhome.domain.User">
        select * from user where username=#{user.username}
    </select>

如果我们使用的是包装类作为参数,比如这个示例的QueryVo类作为findUserByVo()方法的参数,那么在使用时,因为QueryVo类中有一个User类的user对象,而这个user对象中才能找到username属性,所以我们在访问属性时,就使用OGNL表达式才访问对象的属性,即#{user.username}。

编写测试类:

	@Test
    public void selectUser() {
        User user = new User();
        user.setUsername("海哥");
        QueryVo qv = new QueryVo();
        qv.setUser(user);
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        List<User> list = userDao.findUserByQueryVO(qv);
        for (User users : list) {
            System.out.println(users);
        }
    }

6.3 Mybatis的输出结果封装

6.3.1 resultType(输出类型) 输出简单类型

看下边的例子输出整型:

IUserDao.xml文件

<!-- 获取用户的总记录条数 -->
<select id="findTotal" resultType="int">
    select count(*) from user;
</select>

IUserDao.java

/**
 *查询用户数
 */
void findTotal();

测试类文件

/**
 * 测试查询总记录条数
 */
@Test
public void testFindTotal(){
    //5.执行查询一个方法
    int count = userDao.findTotal();
    System.out.println(count);
}

6.3.2 resultType(输出类型) 简单对象的数据类型

(1)让数据库的字段和实体类的属性一致

参考上述[查找所有用户的案例]点击跳转


(2)数据库中的字段和对象中的属性不一致:

修改iy.home.domain.User.java

public class User implements Serializable {
    private int id;
    //username- > name
    private String name;
    //sex -> gender
    private String gender;
    private Date birthday;
    private String address;
	
	//getter
	//setter
	
    @Override
    public String toString() {
        //...
    }
}

在不一致的情况下,如果不改动IUserDao.xml文件,那么不一致的字段查询到的值为null值.
SSM-Mybatis(一)单表CURD所以需要我们做一个手动匹配.方案有两种
方案一
通过改别名的方式 , 修改UserDao.xml

	<!--查找所有-->
    <select id="findAll" resultType="cn.iyhome.domain.User">
        /*select * from user*/
        select id,username as name,sex as gender ,birthday,address from user
    </select>

查询结果:
SSM-Mybatis(一)单表CURD方案二(推荐)

使用resultMap,修改UserDao.xml

	<!--查找所有-->
    <select id="findAll" resultMap="userMap">
        select * from user
        /*select id,username as name,sex as gender ,birthday,address from user*/
    </select>
        
    <resultMap id="userMap" type="cn.iyhome.domain.User">
        <!--id表示主键对应的字段-->
        <id property="id" column="id"/>
        <!--result表示非主键的字段-->
        <result property="name" column="username"/>
        <result property="gender" column="sex"/>
        <!--属性名和列名一致的可以省略,如birthday/address-->
    </resultMap>

<id/>:此属性表示查询结果集的唯一标识。如果是多个字段为复合唯一约束则定义多个<id/>。

​ property:表示User类的属性。

​ column:表示sql查询出来的字段名。

​ column和property放在一块儿表示将sql查询出来的字段映射到指定的pojo类属性上。

<result />:普通属性(普通字段),即pojo的属性。

​ property:表示User类的属性。

​ column:表示sql查询出来的字段名。

​ column和property放在一块儿表示将sql查询出来的字段映射到指定的pojo类属性上。

查询结果:
SSM-Mybatis(一)单表CURD

第7章 Mybatis实现DAO接口的实现类开发(了解)

​ 使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方式(定义实现Dao接口的实现类)和Mapper接口代理开发方式(通用)。而现在主流的开发方式是接口代理开发方式,这种方式总体上更加简便,上述6章我们使用的就是代理方式。

以查找所有用户为例

1.创建工程mybatis_dao_impl

略(/滑稽)

2.导入maven的坐标

需要带入的有: Junit ,mybatis,mysql-connector-java,log4j(自选)

3.编写java类,资源文件,测试类

需要编写的有:
java类:
	cn.iyhome.daomain.User.java
	cn.iyhome.dao.IUerDao.java
	cn.iyhome.dao.impl.IUserDaoImpl.java
资源文件
	resources/cn/iyhome/dao/IUserDao.xml
	resources/SqlMapConfig.xml
	resources/log4j.properties(自选)
测试类:
	test.java.cn.iyhome.test.MybatisTest.java

IUserDaoImpl.java实现类代码

public class IUserDaoImpl implements IUserDao {

    private SqlSessionFactory factory;

    public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
        this.factory = sqlSessionFactory;
    }

    public List<User> findAll() {
        // 根据SqlSessionFactory获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        // 调用SqlSession中的方法,实现查询列表
        // 参数就是能获取匹配信息的key(namespace+"."+id)
        List<User> list = sqlSession.selectList("cn.iyhome.dao.IUserDao.findAll"); 
        // 释放资源
        sqlSession.close();
        return list;
    }
}

测试类MybatisTest.java代码

public class MybatisTest {

    private InputStream in;
    private UserDao userDao;

    @Before//用于在测试方法执行之前执行
    public void init()throws Exception{
        //1.读取配置文件,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.获取dao的实现类对象
        userDao = new UserDaoImpl(factory);
    }

    @After//用于在测试方法执行之后执行
    public void destroy()throws Exception{
        in.close();
    }

    /**
     * 测试查询所有
     */
    @Test
    public void testFindAll(){
        //4.执行查询所有方法
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }
    }
}

其他的增删改查操作类似,不做阐述

在本阶段,只是入门案例,其实还存在很多问题.比如:
1.数据源的配置是否可以抽取
2.SqlMapConfig.xml文件中各种全限定类名很繁琐,是否可以简写
3.如果是动态的sql语句又需要如果编写
4.Mybatis的多表查询又是如何处理的

点击我跳转到Mybatis第二阶段查看

上一篇:Spring + MP + Swagger 完成简单的CURD操作


下一篇:sql中的内连接和外连接