04、Mybatis的CRUD操作

目录

1-1、like模糊查询占位符:不推荐写法'%${value}%'

1-2、like模糊查询:#{username}推荐写法

2、获取保存数据的id(即新增用户id的返回值)

3、使用实体类的包装对象作为查询条件

5、源码:day02_eesy_01mybatisCRUD

6、Mybatis的CRUD操作


com/itheima/dao/IUserDao.xml

1-1、like模糊查询占位符:不推荐写法'%${value}%'

模糊查询的匹配符%写到配置文件时,用到一个固定写法${value};

源码中指定了读取的key的名字就是value,所以在绑定参数时,只能叫value的名字;

<!--依据住址模糊查询用户('%${value}%'不推荐写法)-->
<select id="findByAddress" resultType="com.itheima.domain.User">
    select * from user where address like '%${value}%'
</select>    
@Test
// 测试依据住址模糊查询用户(不推荐写法)
public void testFindByAddress(){
    // 执行依据住址模糊查询用户方法
    List<User> users = userDao.findByAddress("1区");
    for(User u : users){
        System.out.println(u);
    }
}

执行结果:Statement对象的字符串拼接SQL

 

1-2、like模糊查询:#{username}推荐写法

<!--依据姓名模糊查询用户(#{username}推荐写法)-->
<select id="findByUserName" parameterType="string" resultType="com.itheima.domain.User">
    select * from user where username  like #{username}
</select>
@Test
// 测试依据姓名模糊查询用户
public void testFindByUserName(){
    // 5、执行依据姓名模糊查询用户方法
    List<User> users = userDao.findByUserName("%大王%");
    for(User u : users){
        System.out.println(u);
    }
}

执行结果:PrepareStatement的参数占位符

 

2、获取保存数据的id(即新增用户id的返回值

新增用户后,同时要返回当前新增用户的id值,因为id是由数据库的自动增长来实现的,所以就相当于要在新增后将自动增长auto_increment的值返回。

select last_insert_id()将插入数据的主键返回到 object 对象中,得到刚 insert 进去记录的主键值,只适用与自增主键;

如果insert into user(id)values ("55")中,自己写主键的值,执行select last_insert_id(),获取到的主键值是0;

SQL执行语句:

insert into `mybatis`.`user` (`username`, `birthday`, `sex`, `address`) values ('老王', '2020-02-27 17:47:08', '男', '上海市嘉定区');
select last_insert_id();

com/itheima/dao/IUserDao.xml 

<!--保存用户-->
<insert id="saveUser" parameterType="com.itheima.domain.User">
<!--配置插入操作后,获取插入数据的id-->
<!--keyProperty代表要返回的值名称,keyColumn代表数据库列名,order取值为AFTER代表插入后的行为,resultType代表返回值的类型-->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
    select last_insert_id();
</selectKey>
    insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
</insert>
@Test
// 测试保存用户
public void testSaveUser(){
    User user = new User();
    user.setUsername("小天王");
    user.setSex("女");
    user.setBirthday(new Date());
    user.setAddress("上海市静安区");

    System.out.println("测试保存操作之前:" + user);
    // 5、执行保存用户方法
    userDao.saveUser(user);
    System.out.println("测试保存操作之后:" + user);
}

 执行结果:

 

3、使用实体类的包装对象作为查询条件

mybatis的参数

  • parameterType 输入类型
  • 传递简单类型,如int,string等;
  • 传递pojo对象,如com.itheima.domain.User,mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称;
  • 传递pojo包装对象,开发中,通过pojo传递查询条件,查询条件是综合的查询条件,不仅包括用户查询条件,还包括其他的查询条件(如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数,Pojo类中包含pojo;

 

OGNL表达式:Object Graphic Navigation Language 对象 图 导航 语言

  • 它是通过对象的取值方法来获取数据,在写法上把get给省略了,如getId(),省略了get 

如我们获取用户的名称

  • 类中的写法:user.getUsername();
  • OGNL表达式写法:user.username

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

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

 

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

自己自定义了一个综合查询条件对象QueryVo,里面包含用户pojo user,也可以包含其他的信息;

将查询条件对象QueryVo作为一个参数传递进去

com.itheima.domain.QueryVo

package com.itheima.domain;

/**
 * @author nikey
 * @date 2020/3/20
 *  把实体类再包装一层,由多个对象组成一个查询条件,实现数据的查询
 */
public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

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

com.itheima.dao.IUserDao

// 根据queryVo中的条件查询用户
List<User> findUserByVo(QueryVo queryVo);

com/itheima/dao/IUserDao.xml

<!--根据queryVo中的条件查询用户,实体类包装起来做查询-->
<select id="findUserByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User">
    <!--user是QueryVo对象中的属性,要用user.username-->
    select * from user where username like #{user.username}
</select>
@Test
// 测试根据queryVo中的条件查询用户
public void testQueryVo(){
    // 5、执行根据queryVo中的条件查询用户方法
    QueryVo vo = new QueryVo();
    User user = new User();
    user.setUsername("%小%");
    vo.setUser(user);

    List<User> users = userDao.findUserByVo(vo);
    for(User u : users){
        System.out.println(u);
    }
}

 

4、mybatis的输出结果封装

  • resultType 输出类型
  • 输出简单类型,如resultType="int",resultType="string"
  • 输出pojo对象,如resultType="com.itheima.domain.User"
  • 输出pojo列表

 

  • resultType可以指定pojo,将查询结果映射为pojo,但需要pojo的属性名sql查询的列名一致,才可映射成功;
  • 如果sql查询字段名和pojo的属性名不一致,可通过resultMap将字段名和属性名作一个对应关系,resultMap实质上,还需要将查询结果映射到pojo对象中;
  • resultMap可以实现查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list,实现一对一查询和一对多查询;

需求:如果返回的列名和实体类的属性不一致时,就不能封装结果集到指定的实体对象

实现方法有2种:

mysql数据库在windows系统下,不区分大小写,列名是username,实体类属性是userName,实体类属性可以映射到返回的内容;

linux操作系统,严格区分大小写的,username封装不到userName中;

1)SQL语句中,给列名起别名,可以返回的列名和实体类的属性不一致问题;在sql语句层面上解决了问题;

com/itheima/dao/IUserDao2.xml

<select id="findAll" resultType="com.itheima.domain.User2">
    select id as userId, username as userName,birthday as userBirthday, sex as userSex, address as userAddress from user
</select>
package com.itheima.domain;

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

/**
 * @author nikey
 * @date 2020/3/19
 */
public class User2 implements Serializable {
    //  User实例类属性要与数据库user表中的列名一样
    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 + '\'' +
                '}';
    }
}

 

2)采用配置的方式,配置查询结果的列名实体类的属性名的对应关系

com/itheima/dao/IUserDao2.xml

<!--返回的列名和实体类的属性不一致-->
<mapper namespace="com.itheima.dao.IUserDao2">
    <!--采用配置的方式,配置查询结果的列名和实体类的属性名的对应关系-->
    <!--id是唯一标志,type表示查询的实体类是哪一个实体类类型-->
    <resultMap id="userMap" type="com.itheima.domain.User2">
        <!--主键字段的对应-->
        <id property="userId" column="id" />
        <!--非主键字段的对应-->
        <result property="userAddress" column="address"/>
        <result property="userBirthday" column="birthday"/>
        <result property="userName" column="username"/>
        <result property="userSex" column="sex"/>
    </resultMap>

    <!--依据用户id查询用户信息-->
    <select id="findById" parameterType="integer" resultMap="userMap" >
        select * from user where id = #{userId}
    </select>
</mapper>
  • 第一种方法,执行效率快,SQL语句起别名,开发改造量比较大;
  • 第二种方法,开发效率快,只需要配置一个查询结果的列名和实体类的属性名的对应关系<resultMap>,所有的查询操作,都可以改造成resultMap="userMap";

 

5、源码:day02_eesy_01mybatisCRUD

 

6、Mybatis的CRUD操作

com.itheima.dao.IUserDao

package com.itheima.dao;

import com.itheima.domain.QueryVo;
import com.itheima.domain.User;
import java.util.List;

/**
 * @author nikey
 * @date 2020/3/19
 * 用户的持久层接口
 */
public interface IUserDao {
    // 查询所有操作
    List<User> findAll();

    // 依据用户id查询用户信息
    User findById(Integer id);

    // 依据姓名模糊查询用户
    List<User> findByUserName(String username);

    // 依据住址模糊查询用户
    List<User> findByAddress(String address);

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

    // 根据queryVo中的条件查询用户
    List<User> findUserByVo(QueryVo queryVo);

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

    // 更新用户操作
    void updateUser(User user);

    // 删除用户操作
    void deleteUser(Integer id);
}

com.itheima.domain.User

package com.itheima.domain;

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

/**
 * @author nikey
 * @date 2020/3/19
 */
public class User implements Serializable {
    //  User实例类属性要与数据库user表中的列名一样
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    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 + '\'' +
                '}';
    }
}

com.itheima.domain.QueryVo

package com.itheima.domain;

/**
 * @author nikey
 * @date 2020/3/20
 *  把实体类再包装一层,由多个对象组成一个查询条件,实现数据的查询
 */
public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

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

SqlMapConfig.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">
<!--mybatis的主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!-- 配置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://192.168.171.131:3306/mybatis?characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!-- 配置映射文件的位置,映射配置文件指每个dao独立的配置文件 -->
        <mapper resource="com/itheima/dao/IUserDao.xml"/>
    </mappers>
</configuration>

com/itheima/dao/IUserDao.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">

<!-- 命名空间,xml文件和dao接口对接起来 -->
<!--dao的全限定类名-->
<mapper namespace="com.itheima.dao.IUserDao">
    <select id="findAll" resultType="com.itheima.domain.User">
        select * from user
    </select>

    <!--保存用户-->
    <insert id="saveUser" parameterType="com.itheima.domain.User">
    <!--配置插入操作后,获取插入数据的id-->
    <!--keyProperty代表要返回的值名称,keyColumn代表数据库列名,order取值为AFTER代表插入后的行为,resultType代表返回值的类型-->
    <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
        select last_insert_id();
    </selectKey>
        insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
    </insert>

<!--更新用户-->
    <update id="updateUser" parameterType="com.itheima.domain.User">
        update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id = #{id}
    </update>

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

    <!--依据用户id查询用户信息-->
    <select id="findById" parameterType="integer" resultType="com.itheima.domain.User" >
        select * from user where id = #{id}
    </select>

    <!--依据姓名模糊查询用户(#{username}推荐写法)-->
    <select id="findByUserName" parameterType="string" resultType="com.itheima.domain.User">
        select * from user where username  like #{username}
    </select>

    <!--查询总用户数-->
    <select id="findTotal" resultType="int">
        select count(*) from user
    </select>

    <!--依据住址模糊查询用户('%${value}%'不推荐写法)-->
    <select id="findByAddress" resultType="com.itheima.domain.User">
        select * from user where address like '%${value}%'
    </select>

    <!--根据queryVo中的条件查询用户,实体类包装起来做查询-->
    <select id="findUserByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User">
        <!--user是QueryVo对象中的属性,要用user.username-->
        select * from user where username like #{user.username}
    </select>
</mapper>

com.itheima.test.MybatisTest

package com.itheima.test;

import com.itheima.dao.IUserDao;
import com.itheima.domain.QueryVo;
import com.itheima.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 java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

/**
 * @author nikey
 * @date 2020/3/19
 */
public class MybatisTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private IUserDao userDao;

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

    @After  // 用于在测试方法执行之后执行
    public void destroy() throws IOException {
        // 提交事务
        session.commit();

        // 释放资源
        session.close();
        in.close();
    }

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

    @Test
    // 测试保存用户
    public void testSaveUser(){
        User user = new User();
        user.setUsername("小天王");
        user.setSex("女");
        user.setBirthday(new Date());
        user.setAddress("上海市静安区");

        System.out.println("测试保存操作之前:" + user);
        // 5、执行保存用户方法
        userDao.saveUser(user);
        System.out.println("测试保存操作之后:" + user);
    }

    @Test
    // 测试更新用户
    public void testUpdateUser(){
        User user = new User();
        user.setId(48);
        user.setUsername("我是更新用户48");
        user.setAddress("我家在上海市48区");
        user.setBirthday(new Date());
        user.setSex("女");

        // 5、执行更新用户方法
        userDao.updateUser(user);
        User u = userDao.findById(48);
        System.out.println(u);
    }

    @Test
    // 测试删除用户
    public void testDeleteUser(){
        // 5、执行删除用户方法
        userDao.deleteUser(49);
        System.out.println("删除用户成功.......");
    }

    @Test
    // 测试依据用户id查询用户信息
    public void testFindById(){
        // 5、执行依据用户id查询用户信息方法
        User user = userDao.findById(45);
        System.out.println(user);
    }

    @Test
    // 测试依据姓名模糊查询用户
    public void testFindByUserName(){
        // 5、执行依据姓名模糊查询用户方法
        List<User> users = userDao.findByUserName("%大王%");
        for(User u : users){
            System.out.println(u);
        }
    }

    @Test
    // 测试查询总用户数
    public void testFindTotal(){
        // 5、执行查询总用户数方法
        int total = userDao.findTotal();
        System.out.println(total);
    }

    @Test
    // 测试依据住址模糊查询用户(不推荐写法)
    public void testFindByAddress(){
        // 执行依据住址模糊查询用户方法
        List<User> users = userDao.findByAddress("1区");
        for(User u : users){
            System.out.println(u);
        }
    }

    @Test
    // 测试根据queryVo中的条件查询用户
    public void testQueryVo(){
        // 5、执行根据queryVo中的条件查询用户方法
        QueryVo vo = new QueryVo();
        User user = new User();
        user.setUsername("%小%");
        vo.setUser(user);

        List<User> users = userDao.findUserByVo(vo);
        for(User u : users){
            System.out.println(u);
        }
    }
}

day02_eesy_01mybatisCRUD/pom.xml

<?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>day02_eesy_01mybatisCRUD</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
    <!--mybatis-->
    <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.6</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>

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值