10.29Mybatis框架学习

Posted 俊king

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10.29Mybatis框架学习相关的知识,希望对你有一定的参考价值。

10.29Mybatis框架学习

章节内容

  • Mybatis是什么?

  • Mybatis环境配置


什么是Mybatis

概念:

一个开源、轻量级的数据持久化框架

支持定制化 SQL、存储过程以及高级映射,可以在实体类和 SQL 语句之间建立映射关系,是一种半自动化的 ORM 实现。

优点:

  • 内部封装了 JDBC,简化了加载驱动、创建连接、创建 statement 等繁杂的过程

  • 性能优秀、小巧、简单易学、应用广泛

什么是ORM

概念:

ORM(Object Relational Mapping,对象关系映射)是一种数据持久化技术

特点:

通过JavaBean对象去操作数据库

什么是持久化

将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中数据模型的统称。

举例:

文件的存储、数据的读取以及对数据表的增删改查等都是数据持久化操作。

核心要点

MyBatis 的主要思想是将程序中的大量 SQL 语句剥离出来,使用 XML 文件或注解的方式实现 SQL 的灵活配置,将 SQL 语句与程序代码分离,在不修改程序代码的情况下,直接在配置文件中修改 SQL 语句。

Mybatis安装

包括:

  • Mybatis下载

  • Mybatis目录结构

由于自己是使用Maven进行包管理的。所以:

    <!--导入Mybatis依赖-->
   <dependencies>
       <!--mybatis依赖-->
       <dependency>
           <groupId>org.mybatis</groupId>
           <artifactId>mybatis</artifactId>
           <version>3.5.5</version>
       </dependency>

       <!--mysql依赖-->
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>8.0.19</version>
       </dependency>
   </dependencies>

Mybatis文件目录结构包括:

名称说明
asm-7.1.jar 操作Java字节码的类库
cglib-3.3.0.jar 用来动态继承Java类或实现接口
commons-logging-1.2.jar 用于通用日志处理
javassist-3.27.0-GA.jar 分析、编码和创建Java类库
log4j-1.2.17.jar 日志系统
log4j-api-2.13.3.jar log4j到log4j2的桥接包
log4j-core-2.13.3.jar log4j到log4j2的桥接包
ognl-3.2.14.jar OGNL的类库
slf4j-api-1.7.30.jar 日志系统的封装,对外提供统一的API接口
slf4j-log4j12-1.7.30.jar slf4j 对 log4j 的相应驱动,完成 slf4j 绑定 log4j

Mybatis项目的目录结构

这里是下面的项目的目录结构:

/MybatisStudy
/.idea
/src
/main
/java
/resources
/webapp
/WEB-INF
/test
/target

创建Mybatis程序的步骤:

  • 导入依赖--->编写Mybatis核心配置文件--->创建实体类--->创建DAO接口--->创建SQL映射文件--->编写测试类

It\'s a lonely road!!!

Mybatis框架学习笔记

本篇Mybatis框架学习笔记;紧跟之前的学习
Mybatis框架学习笔记(2)—>

在mybatis框架核心配置文件中需要学习的配置
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

1.关于在sql语句中使用 #{} 与${} 的区别

使用 #{}

回忆一下整理第一篇笔记时,当时的mapper.xml配置文件中,添加用户的sql;
当时用的是 #{ } 来得到对象中的值

<?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.xiaozhi.mapper.UserMapper">
    
    <!--添加新用户的sql-->
    <!--这里的parameterType 参数类型 就用刚才配置的别名 user了-->
    <insert id="addUser"  parameterType="user">
        insert into t_user(account,password,address)
        values (#{account},#{password},#{address})
    </insert>

</mapper>

测试使用

@Test
public void testAddUser(){
    //创建用户对象;
    User user = new User("点金手","431231w","四川成都");

    //使用工具类创建sqlSession;
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    //获取代理对象;
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    //调用方法;这里实际上会执行sql语句;
    mapper.addUser(user);
    //事务提交;
    sqlSession.commit();
    //关闭sqlSession;
    sqlSession.close();
}

可以看看测试打印的日志;
出现了占位符 ?,?,?

也就是说,他用了PreparedStatement来进行执行sql的;是比较安全的;可防止sql注入

使用${}

实际上,也可以用${ } ;

Ok,那就来试试;
UserMapper.xml中更换sql

<insert id="addUser"  parameterType="user">
        insert into t_user(account,password,address)
        values (${account},${password},${address})
</insert>

执行测试

//使用${}方式传递参数执行sql;
 @Test
 public void testAddUser2(){
     //创建用户对象;
     User user = new User("阿飞","123132","四川成都");

     //使用工具类创建sqlSession;
     SqlSession sqlSession = MyBatisUtils.getSqlSession();
     //获取代理对象;
     UserMapper mapper = sqlSession.getMapper(UserMapper.class);
     //调用方法;这里实际上会执行sql语句;
     mapper.addUser(user);
     //事务提交;
     sqlSession.commit();
     //关闭sqlSession;
     sqlSession.close();
 }

执行,诶,出现错误了;它直接把输入的赋值直接写到sql语句里面了; 而且是把输入的赋值当做数据库的列名了;所以首先提示找不到列名为 阿飞 的列;这里已经错了后面的自然不会再执行下去了;
要知道,这几个属性赋值的时候是字符串哦;在数据库中字符串赋值的时候,要加''或者"";

那么,修改一下sql语句吧

<insert id="addUser"  parameterType="user">
        insert into t_user(account,password,address)
        values ('${account}','${password}','${address}')
</insert>

再次执行;
OK,执行成功了;
添加时;它是直接按拼接字符串的方式;将对象赋值给传递进去了;

${}方式执行sql时,实际上是Statement的方式;也就是说不安全的那个; 不能防止SQL注入

但是;${}也是可以使用的,
因为用${} 传递的是列名,而不是传递数据;

2.在执行sql后,获取到数据表的主键值;

在之前进行的添加用户中,由于当时数据表的ID是作为主键自动递增的;
在执行完添加语句后,我想快速的得到这个刚刚添加的数据的ID;
那么直接获取Id,得到的肯定是0啊;

试试看—>

//在添加用户数据之后,立即得到主键ID的值;
@Test
public void testAddUser3(){
    //创建用户对象;
    User user = new User("爱喝水","123132","陕西西安");

    //使用工具类创建sqlSession;
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    //获取代理对象;
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    //调用方法;这里实际上会执行sql语句;
    mapper.addUser(user);
    System.out.println("当前的用户Id值为-->"+user.getId());
    //事务提交;
    sqlSession.commit();
    //关闭sqlSession;
    sqlSession.close();
}

执行一下;用户肯定存入了;但是这里输出得到的ID是0;

看看数据表,该用户的ID是24哦

当然,可以写两个sql语句;就是说,刚刚添加的新用户数据之后,然后我又去根据用户的某个信息查询得到他的ID信息;这种方式是可行的;

但是,还有一种个比较好的方式,在执行sql语句后,不需要去另外执行别的sql语句;也能得到用户的ID;
那就是在UserMapper.xml的配置文件中,写sql语句的时候;将参数useGeneratedKeys设置为true;即使用生成的主键;当然还要设置数据库的列名和类中的属性对应;

<!--在执行后,想要得到数据表的主键值              确认使用主键                  数据表的列名      实体类的对应属性-->
<insert id="addUser"  parameterType="user" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
     insert into t_user(account,password,address)
     values (#{account},#{password},#{address})
</insert>

再次测试执行;

//在添加用户数据之后,立即得到主键ID的值;
@Test
public void testAddUser4(){
    //创建用户对象;
    User user = new User("小咸鱼","123132","四川成都");
    //使用工具类创建sqlSession;
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    //获取代理对象;
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    //调用方法;这里实际上会执行sql语句;
    mapper.addUser(user);
    System.out.println("当前的用户Id值为-->"+user.getId());
    //事务提交;
    sqlSession.commit();
    //关闭sqlSession;
    sqlSession.close();
}

执行;得到了主键ID号

3.写个修改用户信息

用户的实体类,改变一下,也就是添加个新的有参构造方法;以及toString()方法

package com.xiaozhi.pojo;

/**
 * @author by CSDN@小智RE0
 * @date 2021-10-24 22:07
 * 实体类User(用户类)
 */
public class User {
    //属性,id,账户,密码,地址;
    private int id;
    private String account;
    private String password;
    private String address;

    //构造方法;
    public User() {

    }

    public User(int id, String account, String password, String address) {
        this.id = id;
        this.account = account;
        this.password = password;
        this.address = address;
    }

    //这里构造方法初始化时就没包括ID;
    public User(String account, String password, String address) {
        this.account = account;
        this.password = password;
        this.address = address;
    }

    //getter,setter;

    public int getId() {
        return id;
    }

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

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getAddress() {
        return address;
    }

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

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

当然,首先在UserMapper持久层接口定义方法;

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

然后在UserMapper.xml映射文件中编写对应的sql文件

<!--修改用户信息 参数为基本类型,可以不标注-->
<update id="updateUser">
    update t_user set account=#{account},password=#{password},address=#{address}
    where id=#{id}
</update>

测试执行

//修改用户信息;
@Test
public void updateUser(){
    //创建用户对象;
    User user = new User(25,"学习mybatis框架","12weds","陕西");
    //使用工具类创建sqlSession;
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    //获取代理对象;
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    //调用方法;
    userMapper.updateUser(user);
    //事务提交;
    sqlSession.commit();
    //关闭sqlSession;
    sqlSession.close();
}

执行成功

4.写个删除用户

UserMapper持久层接口定义方法;

//根据ID删除用户;
void deleteUser(int id);

UserMapper.xml映射文件中编写对应的sql文件

<!--删除用户信息-->
<delete id="deleteUser">
    delete from t_user where id=#{id}
</delete>

测试执行

//删除用户信息;
@Test
public void deleteUser(){
    //使用工具类创建sqlSession;
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    //获取代理对象;
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    //调用方法;
    userMapper.deleteUser(20);
    //事务提交;
    sqlSession.commit();
    //关闭sqlSession;
    sqlSession.close();
}

执行;删除成功;

5.查询所有用户

UserMapper持久层接口定义方法;

//查询所有用户;
List<User> findUser();

UserMapper.xml映射文件中编写对应的sql文件

<!--查询所有用户-->
<select id="findUser" resultType="user">
    select * from t_user
</select>

测试执行

//查询所有用户;
@Test
public  void findAllUser(){
    //使用工具类创建sqlSession;
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    //获取代理对象;
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    //调用方法;
    List<User> user = userMapper.findUser();
    System.out.println(user);
    //事务提交;
    sqlSession.commit();
    //关闭sqlSession;
    sqlSession.close();
}

执行;

6.根据Id查询用户

UserMapper持久层接口定义方法;

//根据用户ID获取;
User findUserById(int id);

UserMapper.xml映射文件中编写对应的sql文件

<!--根据Id查询信息-->
<select id="findUserById" resultType="user">
    select * from t_user where id=#{id};
</select>

测试执行

//根据Id查询用户信息;
@Test
public  void findUserById(){
    //使用工具类创建sqlSession;
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    //获取代理对象;
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    //调用方法;
    User userById = userMapper.findUserById(25);
    System.out.println(userById);
    //事务提交;
    sqlSession.commit();
    //关闭sqlSession;
    sqlSession.close();
}

执行成功;

7.配置开启驼峰命名匹配

有没有注意到;前面在查询信息时,没有进行指定要获取的指定属性;它就自动匹配到用户类的对象属性中了;这是由于当时写实体类时,把属性名和数据库的列名一致了

那么,我要是数据表的列名和用户类的属性不相同了呢?

比如说,这里我把用户类的地址属性改了原来是address;现在我把它改成addRess,驼峰命名的方式;

package com.xiaozhi.pojo;

/**
 * @author by CSDN@小智RE0
 * @date 2021-10-27 1:48
 * 实体类User(用户类)
 */
public class User {
    //属性,id,账户,密码,地址;
    private int id;
    private String account;
    private String password;
    private String addRess;

    //构造方法;
    public User() {

    }

    public User(int id, String account, String password, String addRess) {
        this.id = id;
        this.account = account;
        this.password = password;
        this.addRess = addRess;
    }

    //这里构造方法初始化时就没包括ID;
    public User(String account, String password, String addRess) {
        this.account = account;
        this.password = password;
        this.addRess = addRess;
    }
    
    //getter,setter;
    public int getId() {
        return id;
    }

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

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getAddRess() {
        return addRess;
    }

    public void setAddRess(String addRess) {
        this.addRess = addRess;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", account='" + account + '\\'' +
                ", password='" + password + '\\'' +
                ", addRess='" + addRess + '\\'' +
                '}';
    }
}

然后我把数据表的地址由address改为了add_ress

这时我再根据ID查询信息时,地址查不到信息;

实际上,这里需要在mybatis的核心配置文件mybatis-config.xml中进行一个设置

settings下配置mapUnderscoreToCamelCase为true

是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。
它默认为false关闭状态的;

<?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>
    <!--引入外部的资源文件-->
    <properties resource="database.properties">
    </properties>

    <settings>
        <!--配置日志-->
        <setting name以上是关于10.29Mybatis框架学习的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis框架—动态 SQL配置文件事务

Spring+SpringMVC+MyBatis+Maven框架整合

mybatis学习 mybatis框架的特性

Mybatis框架学习——我的第一个Mybatis程序

学习017 Mybatis框架

MyBatis框架学习