day02 mybatis

day02 mybatis

根据id进行查询

UserDao

    /**
     * 根据id查询
     */
    User findUserById(Integer id);

xml代码

<!--
    User findUserById(Integer id);
    parameterType: 表示参数类型 可写可不写
    resultType:表示返回值类型 必须写
    #{id}:表示占位符,这个占位符是一个参数,这个参数来自User对象里面的id,这个地方是一个入参
    当前的参数 只有一个的时候 如果参数䣌数据类型是八大基本数据类型 和String类型的时候 可以随意些
    -->
    <select id="findUserById" parameterType="java.lang.Integer" resultType="com.atguigu.pojo.User">
        select * from user where id = #{id}
    </select>

测试代码

@Test
public void testFindUserById(){
    User user = userDao.findUserById(48);
    System.out.println(user);  // User{id=48, username=小马宝莉, password='96543'}

}

模糊查询

核心配置文件.xml 添加日志

 <!--
    logImpl : 表示日志的具体实现
    STDOUT :标准输出
    LOGGING : 日志
    -->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

打印结果

在日志初始化的时候,使用标准输出
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.log4j:

打开JDBC的链接
Opening JDBC Connection
创建链接
Created connection 1020155847.
设置自动提交false
Setting autocommit to false on JDBC Connection 
[com.mysql.cj.jdbc.ConnectionImpl@3cce57c7]
执行SQL语句
==>  Preparing: select * from user where username like ?
==> Parameters: %李%(String)
<==    Columns: id, password, username, birthday
<==        Row: 42, 456, 李四, null
<==      Total: 1
执行结果
User{id=42, password=456, username='李四'}
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3cce57c7]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3cce57c7]
执行完毕之后,把链接对象返回到连接池
Returned connection 1020155847 to pool.

UserDao代码

    /**
     * 模糊查询
     */
    List<User> findUserByName(String name);

模糊查询有两种实现方式

第一种实现方式 使用#{} xml代码

<!--    第一种实现方式使用的是#{}, 从打印出来的结果来看 #表示占位符的意思 也就是?-->
    <select id="findUserByName" parameterType="string" resultType="com.atguigu.pojo.User">
        select * from user where username like #{username}
    </select>

测试代码

    @Test
    public void testFindUserByName(){
//        第一种实现方法 sql中不需要添加sql 传递的参数需要加上%
        List<User> users = userDao.findUserByName("%李%");
        for (User user : users) {
            System.out.println(user);
        }
    }

第二种实现方式 使用${} xml代码

<!--    第二种实现方式-->
<!--
    ${}:从打印结果来看,表示连接符的意思,如果使用的是连接符,这个地方必须使用value
    注意:
        如果mybatis的版本是在3.5.1以下的版本,必须使用value
        如果mybatis的版本是在3.5.1以上的版本 参数如果是八大基本拿数据类型 + 字符串类型 随意写
        为了各位记忆方便 统一记住 必须使用value

    #{} 和 ${}区别
    1 #{} 表示占位符 里面写的是类的属性
    2 ${} 表示连接符 连接符只能使用value
    只有模糊查询的时候 才可以使用${} 其他任何地方都必须使用#{} 为了防止sql注入
        -->
   <!-- <select id="findUserByName" parameterType="string" resultType="com.atguigu.pojo.User">
        select * from user where username like "%${value}%"
    </select>-->

测试代码

    @Test
    public void testFindUserByName(){
        // 第二种实现方法 在sql中添加% 传递的参数不需要加%
        List<User> users = userDao.findUserByName("李");
        for (User user : users) {
            System.out.println(user);
        }
    }

${}:字符串连接 字符串替换 UserDao代码

    /**
     * 使用mybatis的替换
     * 如果有多个参数,二个或两个以上参数就必须使用这个注解 注解里面的参数建议跟形参保持一致
     * @param columName
     * @param columValue
     * @return
     */
    List<User> findByNameOrPassword(@Param("columName") String columName, @Param("columValue") String columValue);

xml代码

<!--    注意:parameterType参数类型是有多个 那么参数类型就不要写
    concat:表示拼接函数 等价'%1%' 一般开发的时候 会使用mysql里面的拼接函数 防止sql注入
    注意:如果参数类型是一个参数 参数可以不写 系统可以认识 可以找到这个参数
    如果参数类型是两个或者两个以上 必须添加一个注解 注解里面的参数必须跟我们需要查询条件的参数保持一致-->
    <select id="findByNameOrPassword" resultType="com.atguigu.pojo.User">
        select * from user where ${columName} like concat('%', #{columValue}, '%')
    </select>

测试代码

    // 通过username或password进行查找
    @Test
    public void testFindByNameOrPassword(){
        // 使用username进行查找
//        List<User> userList = userDao.findByNameOrPassword("username", "李");
        // 使用password进行查找
        List<User> userList = userDao.findByNameOrPassword("password", "9");
        for (User user : userList) {
            System.out.println(user);
        }
    }

注意:${} 除了拼接和替换以外 其他所有的地方 都必须使用#{}

聚合函数

UserDao代码

    /**
     * 查询总用户数
     */
    int findTotal();

xml代码

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

测试代码

    // 测试查询总记录条数
    @Test
    public void testFindTotal(){
        int total = userDao.findTotal();
        System.out.println(total);  // 10
    }

复杂的查询

创建QueryVo类

package com.atguigu.pojo;

public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

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

UserDao代码

    List<User> findByVo(QueryVo vo);

xml代码

 <!--   根据用户名查询#{username}
    #{OGNL}-->
    <select id="findByVo" resultType="com.atguigu.pojo.User" parameterType="com.atguigu.pojo.QueryVo">
        select * from user where username like #{user.username}
    </select>

测试代码

    @Test
    public void testFindByQueryVo(){
        QueryVo queryVo = new QueryVo();
        User user = new User();
        user.setUsername("%李%");
        queryVo.setUser(user);
        List<User> users = userDao.findByVo(queryVo);
        for (User user1 : users) {
            System.out.println(user1);
        }
    }

返回结果映射

新建User2类

package com.atguigu.pojo;

public class User2 {
    private Integer id;
    private String userName;
    private String pass_word;


    @Override
    public String toString() {
        return "User2{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", pass_word='" + pass_word + '\'' +
                '}';
    }

    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 String getPass_word() {
        return pass_word;
    }

    public void setPass_word(String pass_word) {
        this.pass_word = pass_word;
    }
}

UserDao代码

    List<User2> findAll2();

xml代码

<!--
    id:必须跟下面的resultMap="UserMap" 保持一致
    type:表示返回值的类型
    <id column="id" property="id"></id> 表示主键id跟属性进行映射
    -->
    <resultMap id="userMap" type="com.atguigu.pojo.User2">
        <id column="id" property="id"></id>
        <result column="username" property="userName"></result>
        <result column="password" property="pass_word"></result>
    </resultMap>

    <select id="findAll2" resultMap="userMap">
        select * from user
    </select>

<!--    resultMap和resultType只能2个选1个 返回结果集-->
<!--    resultMap:设置映射关系-->

    <!--<select id="findAll2" resultType="com.atguigu.pojo.User2">
        select id as id, username as userName, password as pass_word from user
    </select>-->

测试代码

    @Test
    public void testFindAll(){
        List<User2> user2List = userDao.findAll2();
        for (User2 user2 : user2List) {
            System.out.println(user2);
        }
    }

设置别名

作用:降低冗余

在核心配置文件里面设置别名

<!--    设置别名-->
    <typeAliases>
<!--        在别名里面设置包名 mybatis会自动的在pojo里面去找他需要的javabean-->
        <package name="com.atguigu.pojo"/>
    </typeAliases>

之后在xml配置文件里面 写参数类型 或者写返回值类型可以直接写对象的名称

<mapper namespace="com.atguigu.dao.UserDao">

    <select id="findAll" resultType="user">
        select * from user
    </select>

</mapper>

抽取数据源

需要在核心配置文件里面获取数据源

<!--    设置数据源的属性-->
    <properties resource="jdbc.properties"></properties>

在资源配置文件resources下面创建jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=123456

修改核心配置文件

 <dataSource type="POOLED">
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>

连接池

mybatis中数据源的配置

测试数据源:

我们的数据源配置就是在SqlMapConfig.xml文件中,具体配置如下:

MyBatis在初始化时,解析此文件,根据 的type属性来创建相应类型的的数据源DataSource,即:

type=”POOLED”:MyBatis会创建PooledDataSource实例

在这里插入图片描述

结论:它是从池中获取一个连接来用。

type=”UNPOOLED” : MyBatis会创建UnpooledDataSource实例

在这里插入图片描述

结论:它是每次创建一个新的连接来用。

所以我们使用连接池的技术会节省连接资源。

mybatis的事务控制

JDBC 中事务的回顾

在 JDBC 中我们可以通过手动方式将事务的提交改为手动方式,通过 setAutoCommit()方法就可以调整。
通过 JDK 文档,我们找到该方法如下:

在这里插入图片描述

那么我们的 Mybatis 框架因为是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的
setAutoCommit()方法来设置事务提交方式的。

Mybatis 中事务提交方式

Mybatis 中事务的提交方式,本质上就是调用 JDBC 的 setAutoCommit()来实现事务控制。
我们运行之前所写的代码:

 @Test
    public void testProxyDao() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获得MyBatis框架生成的UserMapper接口的实现类
        UserDao userMapper = sqlSession.getMapper(UserDao.class);
        User user = userMapper.findById(41);
        System.out.println(user);
        sqlSession.close();
    }

在这里插入图片描述

mybatis自动提交事务的设置

通过上面的研究和分析,现在我们一起思考,为什么 CUD 过程中必须使用 sqlSession.commit()提交事
务?主要原因就是在连接池中取出的连接,都会将调用 connection.setAutoCommit(false)方法,这样我们
就必须使用 sqlSession.commit()方法,相当于使用了 JDBC 中的 connection.commit()方法实现事务提
交。
明白这一点后,我们现在一起尝试不进行手动提交,一样实现 CUD 操作。注释手动提交事物

在这里插入图片描述

我们发现,此时事务就设置为自动提交了,同样可以实现CUD操作时记录的保存。虽然这也是一种方式,但就
编程而言,设置为自动提交方式为 false 再根据情况决定是否进行提交,这种方式更常用。因为我们可以根据业务
情况来决定提交是否进行提交。

Mybatis映射文件深入

动态sql语句概述

Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。

动态sql之if

我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。比如在 id 如果不为空时可以根据 id 查询,
如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。

① 创建工程:

mabatis-dynamic-sql

②添加pom文件

<?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>org.example</groupId>
    <artifactId>day44mybatis-dynamic-sql</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

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

③导入基本配置:

拷贝这五个文件到项目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oeXfnoTW-1667721726513)(C:/Users/ZZC/AppData/Roaming/Typora/typora-user-images/image-20221106153354214.png)]

④在UserDao接口中 添加查询条件的方法

package com.atguigu.dao;

import com.atguigu.pojo.User;

import java.util.List;

public interface UserDao {

    /**
     * 根据条件动态设置sql
     */
    List<User> findByCondition(User user);
}

⑤UserDao.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">

<mapper namespace="com.atguigu.dao.UserDao">
    <select id="findByCondition" parameterType="user" resultType="user">
        select * from user where 1=1
        <if test="id!=null">
            and id=#{id}
        </if>
        <if test="username!=null">
            and username=#{username}
        </if>
        <if test="password!=null">
            and password=#{password}
        </if>
    </select>
</mapper>

测试文件代码

package com.atguigu;

import com.atguigu.dao.UserDao;
import com.atguigu.pojo.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 java.io.IOException;
import java.io.InputStream;
import java.util.List;


public class MybatisTest {


    private UserDao userDao;
    private SqlSession sqlSession;
    private InputStream is;


    @After
    public void after() throws Exception{
        // 提交事务
        sqlSession.commit();
        // 释放资源
        sqlSession.close();
        is.close();
    }



    @Before
    public void before() throws IOException {
        // 1.需要找到核心配置文件
        is = Resources.getResourceAsStream("sqlMapConfig.xml");
        // 2.构建会话工厂
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 3.读取核心配置文件里面的io流
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
        // 4.获取会话对象
        sqlSession = sqlSessionFactory.openSession();
        // 5.通过会话工厂 获取userdao对象
        userDao = sqlSession.getMapper(UserDao.class);

    }

    @Test
    public void testFindByCondition(){
        User user = new User();
        user.setId(43);
        user.setUsername("王安石");
        user.setPassword("123123");
        List<User> userList = userDao.findByCondition(user);
        for (User user1 : userList) {
            System.out.println(user1);
        }

    }
}

where1=1的用处

where 1 = 1,永远为真

where 1 = 1 用于动态SQL,规范语句

where 1=1; 这个条件始终为True,在不定数量查询条件情况下,1=1可以很方便的规范语句。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值