Mybatis框架学习(一)

文章目录

    • Mybatis框架学习(一)
      • 1. 什么是框架
      • 2. 三层架构
      • 3. 持久层的解决方案
      • 4. 回顾传统的JDBC与数据库交互
      • 5. Mybatis框架概述
        • 5.1 ORM思想(Object Relational Mapping)
      • 6. Mybatis环境搭建
        • 6.1 创建一个maven项目
        • 6.2 配置pom.xml,导入jar包
        • 6.3 创建java的User类 和 数据库中的user表
        • 6.4 创建User类的dao接口
        • 6.5 在resources文件夹中创建Mybatis的主配置文件
        • 6.6 创建UserDao的映射文件
      • ==注意:==
        • 如果能严格遵循上面的2/3/4点,我们将无需再写UserDao接口的实现类,因为有很多事情框架都偷偷帮我们搞定了。
      • 7. Mybatis入门案例
        • 1. 添加log4j的属性配置文件log4j.properties
        • 2.入门案例
      • 8. Mybatis注解开发和编写dao接口实现类的方式
        • 1. 用注解的方式替代 映射文件 UserDao.xml或UserMapper.xml
        • 2. 自己编写Dao接口的实现类(了解)
      • 9. Mybatis的CRUD操作
        • 9.1 关于测试类文件MyBatisTest
        • 9.2 保存用户操作
        • 9.3 更新用户操作
        • 9.4 根据ID删除用户操作
        • 9.5 根据ID查找用户操作
        • 9.6 根据名字进行模糊查找(注意)
        • 9.7 查找总的用户条数(Mybatis支持聚合函数查找)
      • 10. OGNL表达式
      • 11. 解决实体类属性和数据库列名不对应的两种方式
        • 1. 我们的user类
        • 2. 改动User类之后,如何进行查询所有操作
        • 方法1:起别名(效率最高)
        • 方法2:运用resultMap(推荐)
      • 12. 感谢

Mybatis框架学习(一)

1. 什么是框架

​ 框架是一件半成品软件,里面封装了很多细节,程序员在这已有的半成品基础上再加上我们自己的业务需求进去,就变成了一件完整的成品软件,好比框架就是一个舞台,舞台已经有了,接下来该怎么表演就看你的业务需求是什么。所以说在开发时,框架帮我们做了一半的工作,封装了很多的细节,使得我们可以更加关注在业务逻辑的实现上,而不是去纠结一些细枝末节的问题,提高开发效率。

2. 三层架构

一般为了方便管理,我们会把整个项目分为三层,我们要学的MyBatis框架就在三层中的持久层中起作用

  1. 表现层:用于展示数据的,也就是前端,SpringMVC框架就是服务于此
  2. 业务层:处理业务需求
  3. 持久层:和数据库交互,负责与数据库交互,Mybatis框架就作用于此

3. 持久层的解决方案

  1. JDBC技术:

    Connection:获取数据库的连接

    PreparedStatement:执行sql语句

    ResultSet:封装与数据库交互后返回的数据

  2. Spring的JdbcTemplate:spring中对JDBC的简单封装,相对于上面直接用JDBC起来要方便不少

  3. Apache的DBUtils:它和spring的JdbcTemplate很像,也是对jdbc的简单疯转

  4. 但是以上的都不是框架,JDBC是java与数据库交互的规范,和框架根本就谈不上关系;JdbcTemplate和DBUtils就有点封装的意味了,但这只是简单的封装,并没有像框架一样提供一套完整的解决方案,只能说是一个工具类而已。

4. 回顾传统的JDBC与数据库交互

    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            //加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            //通过驱动管理类获取数据库链接
            connection = DriverManager
                    .getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8","root", "root");
            //定义 sql 语句 ?表示占位符
                            String sql = "select * from user where username = ?";
            //获取预处理 statement
            preparedStatement = connection.prepareStatement(sql);
            //设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的参数值
            preparedStatement.setString(1, "王五");
            //向数据库发出 sql 执行查询,查询出结果集
            resultSet = preparedStatement.executeQuery();
            //遍历查询结果集
            while(resultSet.next()){
                System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            //释放资源
            if(resultSet!=null){
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(preparedStatement!=null){
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

反思:在上面的代码中,其实我们仅仅是想实现一条sql语句,就是下面这一条

String sql = "select * from user where username = ?";

但是却写了很多的代码作为这条语句的准备工作,比如加载驱动、创建连接、创建preparedStatement,还有善后工作,比如关闭连接资源、关闭preparedStatement,是真的很…,Mybatis框架的出现,让我们得以从这些冗余的工作中解放出来,而仅仅只需关注sql语句本身就行了

5. Mybatis框架概述

mybatis是一个持久层框架,是java编写的,它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,它使用了ORM思想实现了结果集的封装

5.1 ORM思想(Object Relational Mapping)

Object Relational Mapping:对象关系映射

简单来说:就是把数据库表和实体类及实体类的属性对应起来,让我们可以操作实体类就可以实现操作数据库表

比如我在数据库中有一张表叫user表,而在java类中对应有一个User类

数据库中的user表 java中的User类
username userName
id Id

数据库的user表中的username和User类中的userName属性是对应的,我们操作User类的时候就相当是在操作数据库中的user表,这就是映射。

6. Mybatis环境搭建

6.1 创建一个maven项目

6.2 配置pom.xml,导入jar包

在这里我导入了四个jar包,其中mybatis和mysql相关的jar包是必须要有的


<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.0modelVersion>

    <groupId>com.stfgroupId>
    <artifactId>day01artifactId>
    <version>1.0-SNAPSHOTversion>

    <dependencies>
        <dependency>
            
            <groupId>org.mybatisgroupId>
            <artifactId>mybatisartifactId>
            <version>3.4.5version>
        dependency>

        <dependency>
            
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>5.1.6version>
        dependency>

        <dependency>
            
            <groupId>log4jgroupId>
            <artifactId>log4jartifactId>
            <version>1.2.12version>
        dependency>

        <dependency>
            
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.10version>
        dependency>
    dependencies>

project>

6.3 创建java的User类 和 数据库中的user表

1. 数据库中创建一个user表,这个user表我放在一个名叫mybatis的数据库里面

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','女','北京修正');

Mybatis框架学习(一)_第1张图片

2. 创建一个User类

Mybatis框架学习(一)_第2张图片

package domain;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {
    //对应上图user表中的id
    private Integer id;
    //对应上图user表中的username
    private String username;
    //对应上图user表中的birthday
    private Date birthday;
    //对应上图user表中的sex
    private String sex;
    //对应上图user表中的address
    private String address;

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

6.4 创建User类的dao接口

Mybatis框架学习(一)_第3张图片

1. 创建dao接口UserDao

package dao;
import domain.User;
import java.util.List;

/**
 * 用户的持久层接口
 */
public interface UserDao {
    /**
     * 查询所有操作
     * @return
     */
    List<User> findAll();
}

6.5 在resources文件夹中创建Mybatis的主配置文件

1. 在resources文件夹中创建Mybatis的主配置文件

Mybatis框架学习(一)_第4张图片

注意:我这里的mysql密码是root,用户也是root,访问的数据库是mybatis




<configuration>
    
    <environments default="mysql">
        
        <environment id="mysql">
            
            <transactionManager type="JDBC">transactionManager>
            
            <dataSource type="POOLED">
                
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            dataSource>
        environment>
    environments>

    
    <mappers>
        <mapper resource="/dao/UserDao.xml"/>
    mappers>
configuration>

6.6 创建UserDao的映射文件

Mybatis框架学习(一)_第5张图片



<mapper namespace="dao.UserDao">
    
    <select id="findAll" resultType="domain.User">
        select * from user
    select>
mapper>

注意:

  1. 创建UserDao的映射文件时,很多人是把映射文件起名为UserMapper.xml的,我这里把它叫为UserDao.xml也是可以的。

  2. Mybatis的映射配置文件位置必须和dao接口的包结构相同,比如我在dao文件夹下创建了一个UserDao.java,那就要在dao文件夹下创建UserDao.xml或UserMapper.xml

    Mybatis框架学习(一)_第6张图片

  3. 映射配置文件的mapper标签namespaces属性的取值必须是dao接口的全限定类名

    Mybatis框架学习(一)_第7张图片

  4. 映射配置文件的id属性的取值必须是dao接口的方法名,因为我这里是查询操作,所以是select id = ,这里的resultType是查询后返回的类型,必须是全限定类名

    Mybatis框架学习(一)_第8张图片

如果能严格遵循上面的2/3/4点,我们将无需再写UserDao接口的实现类,因为有很多事情框架都偷偷帮我们搞定了。

7. Mybatis入门案例

1. 添加log4j的属性配置文件log4j.properties

这个本来在环境搭建的时候就加进去的,如果没加的话,是看不到日志信息的,会出现红色的

log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
log4j:WARN Please initialize the log4j system properly.

现在我把这个配置文件添加在resource目录下

Mybatis框架学习(一)_第9张图片

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.入门案例

在测试文件夹test文件夹下创建一个MybatisTest类

Mybatis框架学习(一)_第10张图片

import dao.UserDao;
import domain.User;
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;
import java.util.List;

public class MybatisTest {
    /**
     * Mybatis的入门案例
     * @param args
     */
    public static void main(String[] args) throws IOException {
        //1.读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3.使用工厂生产SqlSession对象
        SqlSession session = factory.openSession();
        //4.使用SqlSession创建Dao接口的代理对象,代理操作,不需要创建实现类
        UserDao userDao = session.getMapper(UserDao.class);
        //5.使用代理对象执行方法
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }
        //6.释放资源
        session.close();
        in.close();
    }
}
/* 运行结果:
User{id=41, username='老王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京'}
User{id=42, username='小二王', birthday=Fri Mar 02 15:09:37 CST 2018, sex='女', address='北京金燕龙'}
User{id=43, username='小二王', birthday=Sun Mar 04 11:34:34 CST 2018, sex='女', address='北京金燕龙'}
User{id=45, username='传智播客', birthday=Sun Mar 04 12:04:06 CST 2018, sex='男', address='北京金燕龙'}
User{id=46, username='老王', birthday=Wed Mar 07 17:37:26 CST 2018, sex='男', address='北京'}
User{id=48, username='小马宝莉', birthday=Thu Mar 08 11:44:00 CST 2018, sex='女', address='北京修正'}
 */

8. Mybatis注解开发和编写dao接口实现类的方式

我们可以看到在入门案例的介绍中,虽然说是只关注sql语句本身就行了,但是还是很麻烦,还要特别关注映射文件的写法,不能写错,又要加载配置文件、创建工厂等等,似乎并不是特别方便。

但初学者的话,写得详细一点,多一点,更有利于我们学习,而且现在只是用Mybatis框架而已,等将来再学几个框架,框架一组合起来,我们就会发现真的仅仅只是关注sql语句本身已经足够了。

1. 用注解的方式替代 映射文件 UserDao.xml或UserMapper.xml

用注解的方式来替代xml文件,显然会写得更少

第一步:在UserDao.java文件中加上注解@Select,并指定要执行的sql语句

Mybatis框架学习(一)_第11张图片

第二步:删除刚才创建的UserDao.xml文件,因为有了注解,已经不需要它了

Mybatis框架学习(一)_第12张图片

第三步:在主配置文件SqlMapConfig.xml中更改mapper标签

Mybatis框架学习(一)_第13张图片

2. 自己编写Dao接口的实现类(了解)

注意:在实际开发中,一般是越简便越好,所以一般不写xml映射文件,而采用注解的方式来弄,也不会自己去写实现类,但是出于学习的目的,我们接下来还是尝试一下自己写实现类的方式,而不采用代理对象

第一步:创建UserDao的实现类UserDaoImpl

Mybatis框架学习(一)_第14张图片

import domain.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.List;

public class UserDaoImpl implements UserDao {
    private SqlSessionFactory factory;

    public UserDaoImpl(SqlSessionFactory factory){
        this.factory = factory;
    }
    public List<User> findAll() {
        //1.使用工厂创建SqlSession对象
        SqlSession session = factory.openSession();
        //2.使用session执行查询所有方法,其实这个selectList里面可以写sql语句的,但是
        //如果写sql语句的话,那UserDao接口里面的注解不就完全没意义了吗,既然我们把sql
        //语句写在接口方法findAll的注解上了,那么我们找到这个方法就行
        List<User> users = session.selectList("dao.UserDao.findAll");
        session.close();
        //3.返回查询结果
        return users;
    }
}

第二步:修改测试类MybatisTest

Mybatis框架学习(一)_第15张图片

因为我们用自己的实现类来实现,就不再用代理对象了

Mybatis框架学习(一)_第16张图片

修改后的实现类

import dao.UserDao;
import dao.impl.UserDaoImpl;
import domain.User;
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;
import java.util.List;

public class MybatisTest {
    public static void main(String[] args) throws IOException {
        //1.读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3.创建UserDao接口的实现类对象
        UserDao userDao = new UserDaoImpl(factory);
        //4.执行实现类里面的findAll方法
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }
        //5.释放资源
        in.close();
    }
}

运行,发现结果是正确的

9. Mybatis的CRUD操作

为了能看到更多一点信息,这次的CRUD操作将采用xml映射文件的方式,而不是注解

9.1 关于测试类文件MyBatisTest

因为测试时要创建工厂、获取SqlSession、获取代理对象,如果在测试查找方法、测试删除方法等等方法里面都要重复地创建工厂、获取对象,就会非常麻烦,而且用完还要释放资源。

我们不如创建一个init函数,专门用来创建工厂、获取对象的

创建一个destroy方法,专门用来释放资源的,这样就会让代码看起来简洁一点,比如测试类可以这样写

import dao.UserDao;
import domain.User;
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.After;
import org.junit.Before;
import org.junit.Test;
import org.omg.IOP.ComponentIdHelper;

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

public class MybatisTest {
    private InputStream in;
    private SqlSession sqlSession;
    private UserDao userDao;

    @Before //用于测试方法之前自动执行
    public void init() throws IOException {
        //1.读取配置文件,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.获取SqlSession对象
        sqlSession = factory.openSession();
        //4.获取dao的代理对象
        userDao = sqlSession.getMapper(UserDao.class);
    }

    @After //用于测试方法之后自动执行
    public void destory() throws IOException {
        //5.提交事务
        sqlSession.commit();
        //6.释放资源
        sqlSession.close();
        in.close();
    }

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

9.2 保存用户操作

第一步:在UserDao.java文件中增添保存方法:saveUser

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

第二步:在UserDao.xml中映射该方法


    <insert id="saveUser" parameterType="domain.User">
        insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday});
    insert>

第三步:在测试类MybatisTest中添加测试:testSave

    /**
     * 测试保存操作
     */
    @Test
    public void testSave(){
        User user = new User();
        user.setUsername("mybatis.saveuser");
        user.setAddress("广东省广州市");
        user.setSex("男");
        user.setBirthday(new Date());
        //保存用户
        userDao.saveUser(user);
    }

注意:保存用户中有一个细节,因为用户id在数据库是采用自增长的形式的,存进去前user是没有id的,但是一存到数据库后,数据库表就会给这个user分配一个id,我们可以通过select last_insert_id()获得这个id,并把它set在user里面,select last_insert_id()总的解释就是 将插入数据的主键返回到 user 对象中,我们来实验下

首先, xml文件改成下面这样

        
    <insert id="saveUser" parameterType="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>

然后,测试类这样写,目的是为了看user对象在执行saveUser方法的前后有没有多了个id值

	@Test
    public void testSave(){
        User user = new User();
        user.setUsername("mybatis.saveuser");
        user.setAddress("广东省广州市");
        user.setSex("男");
        user.setBirthday(new Date());
        //user是没有设置id属性的,现在的 id 默认是null
        System.out.println("保存操作之前:" + user);
        //保存用户
        userDao.saveUser(user);
        //看看user现在id是不是有值了
        System.out.println("保存操作之后:" + user);
        //输出结果可以看到id由null变成了54
    }

9.3 更新用户操作

第一步:在UserDao.java文件中增添更新方法:updateUser

    /**
     * 更新,修改用户
     * @param user
     */
    void updateUser(User user);

第二步:在UserDao.xml中映射该方法

    
    <update id="updateUser" parameterType="domain.User">
        update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id};
    update>

第三步:在测试类MybatisTest中添加测试:testUpdateUser

    /**
     * 测试更新操作
     */
	public void testUpdateUser(){
        User user = new User();
        user.setId(41);
        user.setUsername("update");
        user.setAddress("广东省广州市");
        user.setSex("女");
        user.setBirthday(new Date());
        //更新用户
        userDao.updateUser(user);
    }

9.4 根据ID删除用户操作

第一步:在UserDao.java文件中增添更新方法:deleteUser

/**
     * 根据ID删除用户
     * @param userId
     */
    void deleteUser(Integer userId);

第二步:在UserDao.xml中映射该方法

    
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id = #{uid};
    delete>

第三步:在测试类MybatisTest中添加测试:testDeleteUser

    /**
     * 测试删除操作
     */
    @Test
    public void testDeleteUser(){
        //根据Id删除用户
        userDao.deleteUser(41);
    }

9.5 根据ID查找用户操作

第一步:在UserDao.java文件中增添更新方法:findById

	/**
     * 根据ID查找用户
     * @param userId
     */
    User findById(Integer userId);

第二步:在UserDao.xml中映射该方法

    
    <select id="findById" parameterType="java.lang.Integer" resultType="domain.User">
        select * from user where id = #{uid};
    select>

第三步:在测试类MybatisTest中添加测试:testFindUserById

     /**
     * 根据Id查找用户
     */
    @Test
    public void testFindUserById(){
        User user = userDao.findById(42);
        System.out.println(user);
    }

9.6 根据名字进行模糊查找(注意)

第一步:在UserDao.java文件中增添更新方法:findByName

	/**
     * 根据名字模糊查找
     * @param username
     * @return
     */
    List<User> findByName(String username);

第二步:在UserDao.xml中映射该方法

    
    <select id="findByName" parameterType="java.lang.String" resultType="domain.User">
        select * from user where username like #{usernmae};
    select>

第三步:在测试类MybatisTest中添加测试:testFindByName

    /**
     * 根据username进行模糊查询
     */
    @Test
    public void testFindByName(){
        List<User> users = userDao.findByName("%王%");
        for (User user : users) {
            System.out.println(user);
        }
    }

注意:这里有个小细节就是,当模糊查找需要加两个百分号时,比如上面的(%王%),这是在测试类中加的百分号,也可以在xml文件中的映射选项加,那么把UserDao.xml下面的语句

select * from user where username like #{usernmae};

改成这样

select * from user where username like ‘%${value}%’;

同时测试类中也无需自己添加百分号

List<User> users = userDao.findByName("王");

但是改成这样的话,不大好这样子做的话,在底层中是调用的是statement方法,而不是preparestatement,因为statement采用的是拼接字符串的形式完成sql语句的,拼接字符串带来的一个潜在问题就是sql注入,属于危险操作!

9.7 查找总的用户条数(Mybatis支持聚合函数查找)

第一步:在UserDao.java文件中增添更新方法:findTotal

	/**
     * 寻找总的用户条数
     * @return
     */
    int findTotal();

第二步:在UserDao.xml中映射该方法

    
    <select id="findTotal" resultType="java.lang.Integer">
        select count(*) from user;
    select>

第三步:在测试类MybatisTest中添加测试:testFindTotal

    /**
     * 根据username进行模糊查询
     */
    @Test
    public void testFindTotal(){
        int count = userDao.findTotal();
        System.out.println(count);
    }

10. OGNL表达式

Mybatis框架支持OGNL表达式,它的字面意思就是:

Object Graphic Navigation Language

对象 图 导航 语言

它是通过对象的取值方法来获取数据的,在写法上把get给省略了,比如:我们获取用户名称

平时写法是:user.getUsername

ONGL表达式:user.username

Mybatis中为什么能直接写username,而不用user呢,比如

select * from user where username like #{usernmae};

它根本就不用写user.getUsername,因为parameterType已经提供了属性所属的类,所以不需要写对象名

<select id="findByName" parameterType="java.lang.String" resultType="domain.User">

假如parameterType没有直接提供属性所属的类,那就可以用OGNL表达式的写法

我们试着重写一下模糊查询方法findByName

第一步:封装User类

package domain;

public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

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

第二步:在UserDao.java中添加方法fundByVo

    /**
     * 根据OGNL表达式进行模糊查找
     * @param vo
     * @return
     */
    List<User> findByVo(QueryVo vo);

第三步:在xml文件中映射该方法

注意:parameterType那里写的不再是domain.User类了,

    <select id="findByVo" parameterType="domain.QueryVo" resultType="domain.User">
        select * from user where username like #{user.username};
    select>

第四步:编写测试方法

    /**
     * 根据OGNL表达式进行模糊查询
     */
    @Test
    public void testFindByVo(){
        QueryVo vo = new QueryVo();
        User user = new User();
        user.setUsername("%王%");
        vo.setUser(user);
        List<User> users = userDao.findByVo(vo);
        for (User u : users) {
            System.out.println(u);
        }
    }

OGNL也常应用在开发中,当由多个对象组成一个查询条件时,OGNL表达式就会起很大作用,OGNL表达式的字面意思已经说白了,就是对象导航语言,当有多个对象凑在一起时,仍然能方便清晰地找到

11. 解决实体类属性和数据库列名不对应的两种方式

1. 我们的user类

package domain;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {
    //对应数据库user表中的id
    private Integer id;
    //对应数据库user表中的username
    private String username;
    //对应数据库user表中的birthday
    private Date birthday;
    //对应数据库user表中的sex
    private String sex;
    //对应数据库user表中的address
    private String address;

    //各种getter和setter
    public Integer getId() {
        return id;
    }

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

之所以能够操作数据库,是因为User类中的属性和数据库表中的列名是对应关系的,Javabean中的属性指的就是getter方法去掉get剩下的部分,比如getId(),属性就是Id;还有setter方法去掉set剩下的部分,比如setId,属性就是Id,但是MySql数据库中的那个是id,怎么就能对应上呢?注意,Windows系统下的MySQL是不区分大小写的,写Id和写id是一样的。那现在由于某种原因,我决定改动javabean,改动后的属性与数据库中的user表列名不一致了

package domain;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {
    private Integer userId;
    private String name;
    private String userAddress;
    private String userSex;
    private Date userBirthday;

    //属性是UserId,而数据库中的是id,不一致
    public Integer getUserId() {
        return userId;
    }

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

    //属性是Name,而数据库中的是username,不一致
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //属性是UserAddress,而数据库中的是address,不一致
    public String getUserAddress() {
        return userAddress;
    }
    ..........
}

2. 改动User类之后,如何进行查询所有操作

因为数据库中的属性和java类中的属性没办法对应上了,所以再用原来xml映射是无法完成查询所有操作的

之前的xml写的是

	
    <select id="findAll" resultType="domain.User">
        select * from user
    select>

select * from user执行了之后,没办法进行封装返回,因为返回类型是User类,但是属性不一致就不能够把查询到的信息封装到User中返回。

方法1:起别名(效率最高)

我们可以把xml中的映射信息改成

	
    <select id="findAll" resultType="domain.User">
        select id as userId, username as name, address as userAddress, sex as userSex, birthday as userBirthday from user
    select>

测试类中测试一下

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

结果是正常的,证明封装成功了

起别名之后,User类属性和数据库表属性就又能对应上了,而且起别名的效率是最高的,因为这是深入到sql语句层面上进行的改动,但是也很麻烦,好多方法都要这样起别名,万一我以后又要改动User类了呢,又要起…

方法2:运用resultMap(推荐)

在UserDao.xml中配置属性关系,就是查询结果的列名和实体类属性的列名的对应关系

UserDao.xml

	<resultMap id="userMap" type="domain.User">
        
        <id property="userId" column="id">id>
        
        <result property="Name" column="usernmae">result>
        <result property="userAddress" column="address">result>
        <result property="userSex" column="sex">result>
        <result property="userBirthday" column="birthday">result>
    resultMap>
    
    
    <select id="findAll" resultMap="userMap">
        select * from user;
    select>

然后再调用测试方法,发现封装结果没有问题

12. 感谢

以上内容是我观看传智播客视频所做笔记

在这里插入图片描述

你可能感兴趣的:(Mybatis学习)