Mybatis简介(快速入门&curd案例)

Mybatis1-课堂笔记

准备Mybatis环境->单表CURD->动态SQL语句拼接->多表查询;

注解配置

一、Mybatis概述

1. 框架简介

1.1 什么是框架

​ 框架:是整个或部分应用的可重用设计,是可定制化的应用骨架。它可以帮开发人员简化开发过程,提高开发效率。

​ 简而言之,框架是一个应用系统的半成品,开发人员在框架的基础上,根据业务需求开发功能。即:别人搭台,你唱戏。

  • 框架:让开发人员的代码更简单,功能更强
1.2 框架解决了什么问题

框架主要是解决了技术整合问题

​ 一个应用系统,必定要选用大量的技术来完成业务需求,实现功能。这就导致应用系统依赖于具体的技术,一旦技术发生了变化或者出现问题,会对应用系统造成直接的冲击,这是应该避免的。

​ 框架的出现,解决了这个问题:框架是技术的整合。如果使用了框架,在框架基础上进行开发,那么开发人员就可以直接调用框架的API来实现功能,而不需要关注框架的底层具体使用了哪些技术。这就相当于框架“屏蔽”了具体的技术,实现了应用系统功能和技术的解耦。

框架一般处于低层应用平台(如JavaEE)和高层业务逻辑之间

1.3 有哪些常见的框架

​ 每个框架都是要解决一些具体的问题的,我们可以从JavaEE的三层架构,来说一下常见的框架有哪些。

  1. Mybatis:作用在dao层,负责数据库访问的框架。

    ​ 它原本是Apache的一个开源项目ibatis,后来迁移到了Google code,并改名为Mybatis;之后又迁移到了github上。

    ​ 它是一个优秀的Java轻量级dao层框架,对JDBC进行了封装,使开发人员只需要关注SQL语句,而不需要关注JDBC的API执行细节。

    SQL:面向关系的

  2. Hibernate:作用在dao层,负责数据库访问的框架。

    ​ Hibernate是一个完全面向对象的Dao层框架,封装程度非常高,开发人员可以完全以面向对象的方式操作数据库,甚至不需要编写SQL语句。

    ​ 但是,正因为Hibernate的封装程度过高,导致它的执行效率受到了影响,是重量级框架。目前在国内使用的越来越少了。

  3. SpringMVC:作用在web层,负责和客户端交互的框架。

    ​ SpringMVC是Spring Framework的后续产品,受益于Spring框架的流行,并且因为SpringMVC使用简单、和Spring整合简单,导致SpringMVC框架在国内使用的也越来越多。

  4. Struts1/Struts2:作用在web层,负责和客户端交互的框架。

    ​ Struts1是比较老的框架,目前已经基本不使用了。

    ​ Struts2目前使用的也越来越少,逐步被SpringMVC代替

  5. Spring:不是作用在某一层,而是实现web层、Service层、Dao层之间解耦的框架,是三层之间的粘合剂

    ​ Spring框架是为了解决应用开发的复杂性而创建的,任何Java应用都可以从Spring中受益。Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。

小结:
  • 什么是框架:是应用系统的半成品,可以开发人员的代码更简单,但是功能更强

  • 框架解决了干什么问题:解决了技术整合的问题

  • 有哪些常用框架:

    • SSH:Struts1/Struts2 + Spring + Hibernate
    • SSM:SpringMVC + Spring + Mybatis。我们学习的这一套

2. Mybatis简介

2.1 JDBC的问题
  1. 硬编码问题
    • 数据库连接信息的硬编码
    • SQL语句和参数硬编码
    • 结果集封装硬编码
  2. 大量的重复代码
  3. 性能问题
//注册驱动 
//获取连接
//创建statement/预编译对象
//执行SQL语句
//处理结果
//释放资源
  • DBUtils + 连接池:解决了jdbc的一些问题
    • SQL语句是写死的,封装的结果也是代码里写死的:硬编码问题
    • 功能不够强
2.2 Mybatis介绍

​ Mybatis是一个优秀的Java轻量级持久层框架。

  • 它内部封装了JDBC,使开发人员只需要关心SQL语句,而不需要处理繁琐的JDBC步骤
  • 它采用了ORM思想,解决了实体和数据库映射的问题。只要提供好sql语句,配置了映射,Mybatis会自动根据参数值动态生成SQL,执行SQL并把结果封装返回给我们。
  • 它支持XML和注解两种方式配置映射。
2.3 ORM思想

​ ORM:Object Relational Mapping,对象关系映射思想。指把Java对象和数据库的表和字段进行关联映射,从而达到操作Java对象,就相当于操作了数据库。查询了数据库,自动封装成JavaBean对象

小结:
  • Mybatis:解决了jdbc和dbutils的问题,功能更强
  • Mybatis:采用了ORM思想。我们配置了JavaBean对象和表字段的映射关系。我们执行SQL,Mybatis会帮我们把结果封装成JavaBean
  • Mybatis的配置:xml方式和注解方式

3. Mybatis下载

二、Mybatis快速入门

1. 需求描述

查询所有用户信息,获取用户集合List<User>

2. 准备工作

2.1 统一开发环境
  1. 初始化数据库:执行数据库脚本《资料/mybatisdb.sql》
  2. 准备开发环境:jdk1.8, Maven和本地仓库,idea
2.2 实现步骤
  1. 创建Maven项目,准备JavaBean
  2. 编写Mybatis的代码,查询所有用户
  3. 编写测试代码

3. 入门案例

3.1 创建Maven项目,准备JavaBean
1) 创建Maven的java项目

​ 因为只涉及Dao层,不涉及客户端,所以只要创建Java项目即可。项目坐标信息如下:

	groupId:         com.itheima
	artifactId:      mybatis01_quickstart
	version:         1.0-SNAPSHOT
	packing:         jar
2) 在pom.xml中添加依赖
<dependencies>
    <!--Junit单元测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <!--MySql的数据库驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.46</version>
    </dependency>
    <!--Mybatis的jar包-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>
    <!--Mybatis依赖的日志包-->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.10</version>
        <scope>provided</scope>
    </dependency>
</dependencies>
3) 创建JavaBean
public class User {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    //get/set...
    //toString...
}
3.2 编写Mybatis的代码,查询所有用户
1) 创建dao接口(映射器)

​ 在Mybatis里,把dao层的接口称之为映射器(取 调用接口的方法即相当于操作数据库 之意)。

​ 映射器的类名,可以叫XXXMapper,也可以叫XXXDao。我们这里按照之前的习惯,取名UserDao

​ 注意:只要创建接口即可,不需要创建接口的实现类

public interface UserDao {
    List<User> queryAll();  
}
2) 准备映射配置文件xml

注意:

  1. 映射配置文件名称要和映射器类名一样。例如:映射器叫UserDao,那么配置文件就叫UserDao.xml

  2. 映射配置文件位置要和映射器位置一样。例如:映射器在com.itheima.dao里,那么配置文件就应该在resources的com/itheima/dao目录下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EJlAxMdY-1585403917876)(img/image-20200227110903440.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S3LgInC4-1585403917876)(img/image-20200227110940352.png)]

<?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.itheima.dao.UserDao">
    <!--select标签:表示要执行查询语句; id:给接口里哪个方法配置的,写方法名;resultType:结果集封装类型-->
    <select id="queryAll" resultType="com.itheima.domain.User">
        select * from user
    </select>
</mapper>
3) 准备Mybatis的日志配置文件

​ Mybatis支持使用log4j输出执行日志信息,但是需要我们提供log4j的配置文件:log4j.properties

注意:

  1. 如果没有log4j.properties,不影响Mybatis的功能,只是没有详细日志而已
  2. 如果需要日志的话,要把log4j.properties文件放到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

# 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
4) 准备Mybatis的核心配置文件xml

注意:

  1. 核心配置文件的名称随意,我们习惯叫 SqlMapConfig.xml
  2. 核心配置文件的位置随意,我们习惯放到resources的根目录下
<?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">
<!--mybatis的核心配置文件,主要配置数据库连接信息-->
<configuration>
    <!--配置默认的数据库环境-->
    <environments default="mysql_mybatis">
        <!--定义一个数据库连接环境-->
        <environment id="mysql_mybatis">
            <!--设置事务管理方式,固定值JDBC-->
            <transactionManager type="JDBC"/>
            <!--设置数据源,POOLED,UNPOOLED,JNDI,我们使用POOLED-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--  !!!配置映射文件的位置!!!!!!!!!!!!!!这一步千万不要忘记!!!!!!!!!!!!!!  -->
    <mappers>
        <mapper resource="com/itheima/dao/UserDao.xml"/>
    </mappers>
</configuration>
3.3 编写测试代码
	@Test
    public void testQuickStart() throws IOException {
        //1. 读取核心配置文件SqlMapConfig.xml
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2. 创建SqlSessionFactoryBuilder构造者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //3. 使用构造者builder,根据配置文件的信息is,构造一个SqlSessionFactory工厂对象
        SqlSessionFactory factory = builder.build(is);
        //4. 使用工厂对象factory,生产一个SqlSession对象
        SqlSession session = factory.openSession();
        //5. 使用SqlSession对象,获取映射器UserDao接口的代理对象
        UserDao dao = session.getMapper(UserDao.class);
        //6. 调用UserDao代理对象的方法,查询所有用户
        List<User> users = dao.queryAll();
        for (User user : users) {
            System.out.println(user);
        }
        //7. 释放资源
        session.close();
        is.close();
    }

小结

  1. 准备工作

    1. 创建Maven的java项目
    2. 导入依赖坐标:数据库驱动包,mybatis的包,日志log4j包,单元测试junit,lombok
    3. 创建JavaBean
  2. 编写代码,使用Mybatis实现功能

    1. 创建映射器:dao层的一个接口
    2. 创建映射文件xml,在映射文件里写statement配置
      • xml文件位置,和映射器位置相同
      • xml文件名称,和映射器名称相同
    3. 创建核心配置文件,配置数据库环境和映射文件的路径
      • 文件位置:放在resources目录里
      • 文件名称:sqlMapConfig.xml
    4. 创建log4j日志文件:log4j.properties
  3. 功能测试

    //1. 加载配置文件
    InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml");
    
    //2. 获取映射器的代理对象:构造者构造一个工厂,工厂生产一个SqlSession,SqlSession创建代理对象
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(is);
    SqlSession session = factory.openSession();
    UserDao dao = session.getMapper(UserDao.class);
    
    List<User> userList = dao.queryAll();
    
    //3. 释放资源
    session.close();
    is.close();
  • 实际使用mybatis开发,我们通常只要:
    1. 在映射器里增加方法
    2. 在映射文件里增加statement配置:即给方法配置SQL语句等
    3. 使用映射器代理对象,直接调用方法,操作数据库得到结果
  • 其它工作:由Spring、及其它配套的jar包帮我们实现了

4. Mybatis的运行过程分析

三、Mybatis实现CURD

1. 需求说明

针对user表进行CURD操作:

  • 查询全部用户,得到List<User>(上节课快速入门已写过,略)
  • 保存用户(新增用户)
  • 修改用户
  • 删除用户
  • 根据主键查询一个用户,得到User
  • 模糊查询
  • 查询数量

2. 准备Mybatis环境

2.1 创建Maven项目,准备JavaBean
1) 创建Maven的Java项目,坐标为:
    <groupId>com.itheima</groupId>
    <artifactId>day47_mybatis01_curd</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
2) 在pom.xml中添加依赖:
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.46</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
3) 创建JavaBean
public class User {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    //get/set...
    //toString...
}
2.2 准备Mybatis的映射器和配置文件
1) 创建映射器接口UserDao(暂时不需要增加方法,备用)
public interface UserDao {
}
2) 创建映射配置文件UserDao.xml(暂时不需要配置statement,备用)
<?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.itheima.dao.UserDao">
</mapper>
3) 创建Mybatis的核心配置文件
<?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>
    <environments default="mysql_mybatis">
        <environment id="mysql_mybatis">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/itheima/dao/UserDao.xml"/>
    </mappers>
</configuration>
4) 准备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
2.3 准备单元测试类

在单元测试类中准备好@Before、@After的方法代码备用。编写完成一个功能,就增加一个@Test方法即可。

代码如下:

public class MybatisCURDTest {
    private InputStream is;
    private SqlSession session;
    private UserDao dao;

    @Before
    public void init() throws IOException {
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(is);
        session = factory.openSession();
        dao = session.getMapper(UserDao.class);
    }

    @After
    public void destory() throws IOException {
        //释放资源
        session.close();
        is.close();
    }
}

3. 编写代码实现需求

3.1 保存/新增用户
1) 在映射器UserDao中增加方法
void save(User user);
2) 在映射配置文件UserDao.xml中添加statement
<!--parameterType:是方法的参数类型,写全限定类名-->
<insert id="save" parameterType="com.itheima.domain.User">
    <!-- 
            selectKey标签:用于向数据库添加数据之后,获取最新的主键值
                resultType属性:得到的最新主键值的类型
                keyProperty属性:得到的最新主键值,保存到JavaBean的哪个属性上
                order属性:值BEFORE|AFTER,在insert语句执行之前还是之后,查询最新主键值。MySql是AFTER
         -->
    <selectKey resultType="int" keyProperty="id" order="AFTER">
        select last_insert_id()
    </selectKey>

    insert into user (id, username, birthday, address, sex) 
    values (#{id}, #{username}, #{birthday},#{address},#{sex})
</insert>

注意:

​ SQL语句中#{}代表占位符,相当于预编译对象的SQL中的?,具体的值由User类中的属性确定

3) 在单元测试类中编写测试代码
    @Test
    public void testSaveUser(){
        User user = new User();
        user.setUsername("tom");
        user.setAddress("广东深圳");
        user.setBirthday(new Date());
        user.setSex("男");

        System.out.println("保存之前:" + user);//保存之前,User的id为空
        dao.save(user);
        session.commit();//注意:必须要手动提交事务
        System.out.println("保存之后:" + user);//保存之后,User的id有值
    }

注意:执行了DML语句之后,一定要提交事务:session.commit();

插入功能步骤小结
  1. 在映射器里增加方法

  2. 在映射配置文件里增加statement

    <insert id="方法名" parameterType="参数类型,全限定类名">
        <selectKey resultType="int" keyProperty="属性名" order="AFTER">
        	select last_insert_id()
        </selectKey>
        insert语句
    </insert>
  3. 功能测试

    • 执行DML语句之后,一定要提交事务session.commit()
3.2 修改用户
1) 在映射器UserDao中增加方法
void edit(User user);
2) 在映射配置文件UserDao.xml中添加statement
<update id="edit" parameterType="com.itheima.domain.User">
    update user set username = #{username}, birthday = #{birthday}, 
    address = #{address}, sex = #{sex} where id = #{id}
</update>
3) 在单元测试类中编写测试代码
@Test
public void testEditUser(){
    User user = new User();
    user.setId(50);
    user.setUsername("jerry");
    user.setAddress("广东深圳宝安");
    user.setSex("女");
    user.setBirthday(new Date());

    dao.edit(user);
    session.commit();
}

注意:执行了DML语句之后,一定要提交事务:session.commit();

修改功能的小结
  1. 在映射器里增加方法

  2. 在映射配置文件里增加statement

    <update id="方法名称" parameterType="参数类型,全限定类名">
    	update语句
    </update>
  3. 功能测试

    • 执行DML语句,一定要提交事务session.commit()
3.3. 删除用户
1) 在映射器UserDao中增加方法
void delete(Integer id);
2) 在映射配置文件UserDao.xml中增加statement
<delete id="delete" parameterType="int">
    delete from user where id = #{id}
</delete>

注意:

​ 如果只有一个参数,且参数是简单类型的,那么#{id}中的id可以随意写成其它内容,例如:#{abc}

简单类型参数:

​ int, double, short, boolean, … 或者:java.lang.Integer, java.lang.Double, …

​ string 或者 java.lang.String

3) 在单元测试类中编写测试代码
@Test
public void testDeleteUser(){
    dao.delete(50);
    session.commit();
}

注意:执行了DML语句之后,一定要提交事务:session.commit();

删除功能的小结
  1. 在映射器里增加方法

  2. 在映射配置文件里增加statement

    <delete id="方法名称" parameterType="参数类型,写全限定类名">
    	delete from user where id = #{随意写}
    </delete>

    注意:如果SQL语句只有一个参数,并且是简单类型,在#{}里边可以写任意值

  3. 功能测试

    • 注意:执行DML语句之后,要提交事务session.commit()
3.4 根据主键查询一个用户
1) 在映射器UserDao中增加方法
User findById(Integer id);
2) 在映射配置文件UserDao.xml中增加statement
<select id="findById" parameterType="int" resultType="com.itheima.domain.User">
    select * from user where id = #{id}
</select>
3) 在单元测试类中编写测试代码
@Test
public void testFindUserById(){
    User user = dao.findById(48);
    System.out.println(user);
}
3.5 模糊查询
3.5.1 使用#{}方式进行模糊查询
1) 在映射器UserDao中增加方法
/**
 * 使用#{}方式进行模糊查询
 */
List<User> findByUsername1(String username);
2) 在映射配置文件UserDao.xml中增加statement
<select id="findByUsername1" parameterType="string" resultType="com.itheima.domain.User">
    select * from user where username like #{username}
</select>

注意:只有一个参数,且是简单参数时, #{username}中的username可以写成其它任意名称

3) 在单元测试类中编写测试代码
/**
 * 使用#{}方式进行模糊查询--单元测试方法
 */
@Test
public void testFindUserByUsername1(){
    List<User> users = dao.findByUsername1("%王%");
    for (User user : users) {
        System.out.println(user);
    }
}

注意:模糊查询的条件值,前后需要有%

3.5.2 使用${value}方式进行模糊查询
1) 在映射器UserDao中增加方法
/**
 * 使用${value}方式进行模糊查询
 */
List<User> findByUsername2(String username);
2) 在映射配置文件UserDao.xml中增加statement
<select id="findByUsername2" parameterType="string" resultType="com.itheima.domain.User">
   select * from user where username like '%${value}%'
</select>

注意:

​ ${value}是固定写法,不能做任何更改

​ 在SQL语句中已经加了%,那么在测试代码中,传递参数值时就不需要再加%了

3) 在单元测试类中编写测试代码
/**
 * 使用${value}方式进行模糊查询--单元测试方法
 */
@Test
public void testFindUserByUsername2(){
    List<User> users = dao.findByUsername2("王");
    for (User user : users) {
        System.out.println(user);
    }
}

注意:SQL语句中已经加了%, 参数值前后不需要再加%

3.5.3 #{}和${value}的区别(面试题)
  • #{}:表示一个占位符,相当于预编译对象的SQL中的?

    • 可以有效防止SQL注入;
    • Mybatis会自动进行参数的Java类型和JDBC类型转换;
    • #{}写的是属性名称。如果只有一个参数并且是简单类型,里边可以是value或者其它名称
    映射配置文件中的SQL:select * from user where username like #{username}
    单元测试中传递实参:%王%
    
    最终执行的SQL:select * from user where username like ?
    参数值:%王%
    
  • ${}:表示拼接SQL串,相当于把实际参数值,直接替换掉${}

    • 不能防止SQL注入

    • Mybatis不进行参数的Java类型和JDBC类型转换

    • ${}写的是属性名称。如果只有一个参数并且是简单类型,${value}中只能是value,不能是其它名称

      (Mybatis3.4 里存在这种现象,3.5没有了)

    映射配置文件中的SQL:select * from user where username like '%${value}%'
    单元测试中传递实参:王
    
    最终执行的SQL:select * from user where username like '%王%'
    
3.5.4 模糊查询的小结

功能实现的步骤:

  1. 在映射器里增加方法

  2. 在映射配置文件里增加statement

    • 第1种:#{}方式
    <select id="search1" parameterType="java.lang.String" resultType="com.itheima.domain.User">
        select * from user where username like #{username}
    </select>
    • 第2种:${}方式
    <select id="search2" parameterType="java.lang.String" resultType="com.itheima.domain.User">
        select * from user where username like '%${value}%'
    </select>
  3. 功能测试

#{}${}的区别:

  • #{}本质是预编译方式,可以有效防止SQL注入;${}本质是拼接字符串方式,不能防止SQL注入
  • #{}会自动转换Java类型和JDBC类型;${}不会自动转换Java类型和JDBC类型
  • 如果只有一个参数,并且是简单类型:
    • #{}里边可以写任意值
    • ${}里边只能写${value}。(Mybatis3.5之前的版本)
3.6 查询数量(聚合函数)
1) 在映射器UserDao中增加方法
Integer findTotalCount();
2) 在映射配置文件中UserDao.xml增加statement
<select id="findTotalCount" resultType="int">
    select count(*) from user
</select>
3) 在单元测试类中编写测试代码
@Test
public void testFindTotalCount(){
    Integer totalCount = dao.findTotalCount();
    System.out.println(totalCount);
}

4. CURD功能实现的小结

四、Mybatis的参数和结果集

1. OGNL表达式了解

​ OGNL:Object Graphic Navigator Language,是一种表达式语言,用来从Java对象中获取某一属性的值。本质上使用的是JavaBean的getXxx()方法。

  • 例如:user.getUsername()—> user.username

  • 例如:user.getAddress().getProvince()—>user.address.province

    list.size()>0, list != null

​ 在#{}里、${}可以使用OGNL表达式,从JavaBean中获取指定属性的值

2. parameterType

2.1 简单类型
  • 参数写法:

​ 例如:int, double, short 等基本数据类型,或者string

​ 或者:java.lang.Integer, java.lang.Double, java.lang.Short, java.lang.String

  • SQL语句里获取参数:

    如果是一个简单类型参数,写法是:#{随意}

2.2 POJO(JavaBean)
  • 参数写法:

​ 如果parameterType是POJO类型,要写全限定类名

​ 例如:parameterType是com.itheima.domain.User

  • SQL语句里获取参数:#{JavaBean的属性名}
2.3 POJO包装类(复杂JavaBean)–QueryVO
  • 参数写法:

​ 在web应用开发中,通常有综合条件的搜索功能,例如:根据商品名称 和 所属分类 同时进行搜索。这时候通常是把搜索条件封装成JavaBean对象;JavaBean中可能还有JavaBean。

  • SQL里取参数:#{xxx.xx.xx}
2.3.1 功能需求

​ 根据用户名搜索用户信息,查询条件放到QueryVO的user属性中。QueryVO如下:

public class QueryVO {
    private User user;
    //private String className;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}
2.3.1 功能实现
1) 在映射器UserDao中增加方法
List<User> findByVO(QueryVO vo);
2) 在映射配置文件中增加配置信息
<select id="findByVO" parameterType="com.itheima.domain.QueryVO"     resultType="com.itheima.domain.User">
   select * from user where username like #{user.username}
</select>
3) 在单元测试类中编写测试代码
@Test
public void testFindByVO(){
    QueryVO vo = new QueryVO();
    User user = new User();
    user.setUsername("%王%");
    vo.setUser(user);

    List<User> users = dao.findByVO(vo);
    for (User user1 : users) {
        System.out.println(user1);
    }
}

3. resultType

注意:resultType是查询select标签上才有的,用来设置查询的结果集要封装成什么类型的

3.1 简单类型

​ 例如:int, double, short 等基本数据类型,或者string

​ 或者:java.lang.Integer, java.lang.Double, java.lang.Short, java.lang.String

3.2 POJO(JavaBean)

​ 例如:com.itheima.domain.User

注意:JavaBean的属性名要和字段名保持一致

3.3 JavaBean中属性名和字段名不一致的情况处理
3.3.1 功能需求

​ 有JavaBean类User2,属性名和数据库表的字段名不同。要求查询user表的所有数据,封装成User2的集合。其中User2如下:

public class User2 {
    private Integer userId;
    private String username;
    private Date userBirthday;
    private String userSex;
    private String userAddress;

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

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

    public Date getUserBirthday() {
        return userBirthday;
    }

    public void setUserBirthday(Date userBirthday) {
        this.userBirthday = userBirthday;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

    @Override
    public String toString() {
        return "User2{" +
                "userId=" + userId +
                ", username='" + username + '\'' +
                ", userBirthday=" + userBirthday +
                ", userSex='" + userSex + '\'' +
                ", userAddress='" + userAddress + '\'' +
                '}';
    }
}
3.3.2 实现方案一:SQL语句中使用别名,别名和JavaBean属性名保持一致(用的少)
1) 在映射器UserDao中增加方法
/**
 * JavaBean属性名和字段名不一致的情况处理---方案一
 * @return
 */
List<User2> queryAll_plan1();
2) 在映射配置文件UserDao.xml中增加statement
<select id="queryAll_plan1" resultType="com.itheima.domain.User2">
    select id as userId, username as username, birthday as userBirthday, address as userAddress, sex as userSex from user
</select>
3) 在单元测试类中编写测试代码
/**
 * JavaBean属性名和字段名不一致的情况处理---方案一 单元测试代码
 */
@Test
public void testQueryAllUser2_plan1(){
    List<User2> user2List = dao.queryAll_plan1();
    for (User2 user2 : user2List) {
        System.out.println(user2);
    }
}
3.3.3 实现方案二:使用resultMap配置字段名和属性名的对应关系(推荐)
1) 在映射器UserDao中增加方法
/**
 * JavaBean属性名和字段名不一致的情况处理--方案二
 * @return
 */
List<User2> queryAll_plan2();
2) 在映射配置文件UserDao.xml中增加statement
<select id="queryAll_plan2" resultMap="user2Map">
    select * from user
</select>

<!-- 
 resultMap标签:设置结果集中字段名和JavaBean属性的对应关系
     id属性:唯一标识
   type属性:要把查询结果的数据封装成什么对象,写全限定类名 
 -->
<resultMap id="user2Map" type="com.itheima.domain.User2">
    <!--id标签:主键字段配置。  property:JavaBean的属性名;  column:字段名-->
    <id property="userId" column="id"/>
    <!--result标签:非主键字段配置。 property:JavaBean的属性名;  column:字段名-->
    <result property="username" column="username"/>
    <result property="userBirthday" column="birthday"/>
    <result property="userAddress" column="address"/>
    <result property="userSex" column="sex"/>
</resultMap>
3) 在单元测试类中编写测试代码
/**
 * JavaBean属性名和字段名不情况处理--方案二  单元测试代码
 */
@Test
public void testQueryAllUser2_plan2(){
    List<User2> user2List = dao.queryAll_plan2();
    for (User2 user2 : user2List) {
        System.out.println(user2);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值