Mybatis-初学者2

一. MyBatis 的CRUD操作

1:添加操作

略(在1中末尾有体现)

2:删除操作

根据学号删除一条学生信息
步骤:
在StudentDAO中定义删除方法
在这里插入图片描述

在StudentMapper.xml中对接口方法进行"实现"(插件可以生成)
在这里插入图片描述
测试:在StudentDAO的测试类中添加测试方法

  try {

            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            //SqlSessionFactory表示mybatis的会话工厂,工厂模式
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
            //SqlSession 对象是mybatis和数据库之间的连接,也就是会话,创建了连接,可以得到所有的mapper对象(映射关系)
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //通过SqlSession 对象调用getMapper方法获取DAO接口对象
            StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
            //调用被测试方法
            int i = studentDAO.deleteStudent("10001");
            //提交事务
            sqlSession.commit();
            System.out.println(i);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

在这里插入图片描述

3.修改操作

根据学号,修改其他字段信息

<update id="updateStudent">
        update tb_students
        set
            stu_name = #{stuName},
            stu_gender = #{stuGender},
            stu_age = #{stuAge}
        where
            stu_num = #{stuNum}
    </update>
@Test
    public void  testUpdateStudent(){
        try {
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory sqlSessionFactory = builder.build(is);
            SqlSession sqlSession = sqlSessionFactory.openSession();
            StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
            int i = studentDAO.updateStudent(new Student(2,"10002","can","男",18));
            sqlSession.commit();
            assertEquals(1,i);//期望,单元测试的期望返回结果
            System.out.println(i);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

assertEquals(1,i)
如果两者一致, 程序继续往下运行.
如果两者不一致, 中断测试方法, 抛出异常信息 AssertionFailedError .

在这里插入图片描述

4.查询操作-查询所有

  1. 在studentDAO接口中定义方法,返回多条,所以用List集合来装
    在这里插入图片描述
  2. 在studentMapper文件中写
    下面为两种实现方案:法一取别名,法二用resultMap
<!--    resultType执行查询结果,封装的对象的实体类-->
<!--    resultSets指定当前操作返回的集合类型(可省略)-->
<!--    resultType返回的类型-->
<!--    <select id="listStudents" resultType="com.liguoqing.pojo.Student" resultSets="java.util.List">-->
<!--        select-->
<!--            sid as stuId,-->
<!--            stu_num as stuNum,-->
<!--            stu_name as stuName,-->
<!--            stu_gender as stuGender,-->
<!--            stu_age as stuAge-->
<!--        from tb_students-->
<!--    </select>-->

<!--resultMap标签用于定义实体类和数据表的映射关系(ORM)-->
<resultMap id="studentMap" type="com.liguoqing.pojo.Student">
    <id column="sid" property="stuId"/>
    <result column="stu_num" property="stuNum"/>
    <result column="stu_name" property="stuName"/>
    <result column="stu_gender" property="stuGender"/>
    <result column="stu_age" property="stuAge"/>
</resultMap>

<!--    resultMap 用于引用一个实体的映射关系,当配置了resultMap以后,resultType就可以省略-->
<select id="listStudents" resultMap="studentMap">
    select sid,
           stu_num,
           stu_name,
           stu_gender,
           stu_age
    from tb_students
</select>

这里resulttype就可以不写了,因为map里已经有了
在这里插入图片描述

这里直接复制数据库的
在这里插入图片描述

  1. test方法里面写

 @Test
public void testStudentList() {
    try {
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = builder.build(is);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
        List<Student> studentList = studentDAO.listStudents();
        assertNotNull(studentList);
        sqlSession.commit();
        for (Student student : studentList
        ) {
            System.out.println(student);
        }

    } catch (IOException e) {

    }
}

最终得到结果
在这里插入图片描述

5.查询操作-查询一条记录

根据学号查询一个学生信息
和上文同样的方法
几个注意点:

  1. 多个查询操作可以使用同一个map

在这里插入图片描述

  1. 查询不需要提交事务
  2. 牢记三部曲-在StudentDAO中定义接口方法;用插件+自己写的mysql语句在StudentDAOMappperxml 中配置StudentDAO接口的方法实现–SQL;写单元测试

6.查询操作-多参数查询

参数 start ,pagesize

在StudentDAO中定义操作方法,如果方法有多个参数,使用@Param 注解声明参数的别名
package com.liguoqing.dao;

public interface StudentDAO {
    /*
    * 在MyBatis进行操作:
    * 1:如果操作方法只有一个简单类型或者字符串类型的参数,
    * 在Mapper配置中可以直接通过#{key}获取,这个key的占位符号可以随便写
    * 2:如果操作方法有一个对象类型的参数,
    * 在Mapper配置中可以直接通过#{attrName}获取对象的指定属性值(attrName必须是参数对象的属性)
    * 3:如果操作方法有一个Map类型的参数,
    * 在Mapper配置中可以直接通过#{key}获取key的指定value值
    * 4:如果操作方法有多个参数,该如何处理呢?
    * 通过MyBatis自带的参数 arg0 arg1 .. 来获取相应的参数
    * 也可以通过@Param("key") 给参数添加注解的方式
     */
    public int insertStudent(Student student);
    public int deleteStudent(String stuNum);
    public int updateStudent(Student student);
    public List<Student> listStudents();
    public Student queryStudent(String stuNum);
//    public List<Student> listStudentsByPage(HashMap<String,Integer> map);
//    public List<Student> listStudentsByPage(int start,int pageSize);
    public List<Student> listStudentsByPage(@Param("start") int start
                                        ,@Param("pageSize") int pageSize);
}

在StudentMapper.xml配置sql时,使用#{}获取到指定的参数

 <select id="listStudentsByPage" resultMap="studentMap">
            select sid,
                   stu_num,
                   stu_name,
                   stu_gender,
                   stu_age
            from tb_students
                    limit #{start}, #{pageSize}
            <!-- limit #{arg0}, #{arg1}-->
            <!-- limit #{param1}, #{param2}-->

        </select>

—注意:如果DAO操作方法,没有通过@Param指定参数别名,在SQL中也可以通过MyBatis自带的arg0 ,arg1… 或者 param1,param2…获取参数

单元测试

 @Test
    public void testlistStudentsByPage() {
        try {
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory sqlSessionFactory = builder.build(is);
            SqlSession sqlSession = sqlSessionFactory.openSession();
            StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);

//            HashMap<String,Integer> map = new HashMap<String,Integer>();
//            map.put("start",0);
//            map.put("pageSize",2);
//            List<Student> studentList = studentDAO.listStudentsByPage(map);

            List<Student> studentList = studentDAO.listStudentsByPage(0,2);

            assertNotNull(studentList);
            sqlSession.commit();
            for (Student student : studentList
            ) {
                System.out.println(student);
            }
        } catch (IOException e) {

        }
    }

7.查询操作-查询总记录数

StudentDAO

 public int getCount();

在StudentMapper.xml配置sql时,使用 resultType 指定当前操作的返回类型为int(插件自动生成java.lang.Integer也没问题)

<select id="getCount" resultType="int">
    select count(1) from tb_students
</select>

单元测试

@Test
public void testGetStudentCount(){
    try{
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = builder.build(is);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
        int i = studentDAO.getCount();
        System.out.println(i);
    }catch (IOException e){
    }
}

8.添加操作回填生成的主键

在StudentMapper.xml
在insert标签中 useGeneratedKeys 设置添加操作是否需要回填生成的主键 keyProperty 设置回填的位置

  <!--parameterType 这个参数在DAO中已经指定类型了,在这里可以省略-->
<!--    useGeneratedKeys 设置添加操作是否需要回填生成的主键-->
<!--    keyProperty 设置回填的位置-->
    <insert id="insertStudent" parameterType="com.liguoqing.pojo.Student" useGeneratedKeys="true" keyProperty="stuId">
        insert into tb_students(stu_num, stu_name, stu_gender, stu_age)
        values (#{stuNum}, #{stuName}, #{stuGender}, #{stuAge})
    </insert>

二.MyBatis工具类封装

在这里插入图片描述

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;

public class MyBatisUtil {

    private static SqlSessionFactory factory;//单例的
    private static final ThreadLocal<SqlSession> local = new ThreadLocal<SqlSession>(); //线程锁,各个线程之间不影响,例如开启关闭数据库连接之类的

    static {
        try {
            //加载myBatis配置文件,创建会话工厂
            factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //得到sqlSession对象
    public static SqlSession getSqlSession() throws IOException {
        SqlSession sqlSession = local.get();
        if (sqlSession == null){
            sqlSession = factory.openSession();
            local.set(sqlSession);
        }
        return sqlSession;
    }

    public static <T extends Object>T getMapper(Class<T> C) throws IOException {
        SqlSession sqlSession = getSqlSession();
        T dao = sqlSession.getMapper(C);
        return dao;
    }

    public static SqlSessionFactory getFactory() throws IOException {
        if (factory == null){
            factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        }
        return factory;
    }
}

这样就可以简短的写测试内容
在这里插入图片描述

三.事务管理

sqlSession对象的作用:

  1. getMapper(DAO.class) 获取Mapper(DAO接口的实例)
  2. 事务管理
    1:手动提交事务
    sqlSession .commit() 提交事务
    sqlSession.rollback() 事务回滚
@Test
    public void insertStudent() {

        try {
             SqlSession sqlSession = MyBatisUtil.getSqlSession();
             //1:当我们获取sqlSession对象时,就默认开启了事务
            try{
                StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
                Student student = new Student(0, "10005", "java少年", "男", 24);
                int i = studentDAO.insertStudent(student);
                //2:操作完成并成功以后,需要手动提交
                sqlSession.commit();
                System.out.println(student);
                System.out.println(i);
            }catch (Exception e){
                //3:当操作出现异常,调用rollback进行回滚
                sqlSession.rollback();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2:自动提交事务
在这里插入图片描述

sqlSession = factory.openSession(true);//这里的参数,如果不填,默认是false,也就是需要手动进行提交,如果填了true会自动提交事务

待补

四.MyBatis主配置文件

mybatis-config.xml 是MyBatis框架的主配置文件,主要用于配置MyBatis数据源以及工作属性信息
注意:
标签使用时需要注意顺序
空标签会导致报错

7. 配置文件详解

7.1 properties

​ 可以使用properties读取properties配置文件。使用其中的resource属性来设置配置文件的路径。

​ 然后使用${key}来获取配置文件中的值

例如:

在resources目录下有jdbc.properties文件,内容如下:

jdbc.url=jdbc:mysql://localhost:3306/mybatis_db
jdbc.driver=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=root

在mybatis-config.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">
<configuration>
    <!--设置配置文件所在的路径-->
    <properties resource="jdbc.properties"></properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--获取配置文件中配置的对应的值来设置连接相关参数-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

7.2 settings

​ 可以使用该标签来设置进行一些设置

例如:

    <settings>
        <!--开启自动驼峰命名映射-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

具体的设置参考:https://mybatis.org/mybatis-3/zh/configuration.html#settings

7.3 typeAliases

​ 可以用来设置给全类名设置别名,简化书写。一般设置一个包下的类全部具有默认别名。默认别名是类目首字母小写。例如:com.sangeng.pojo.User别名为user

   <typeAliases>
        <package name="com.sangeng.dao"></package>
    </typeAliases>

7.4 environments

​ 配置数据库相关的环境,例如事物管理器,连接池相关参数等。

    <!--设置默认环境-->
	<environments default="development">
        
        <!--设置该环境的唯一标识-->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--获取配置文件中配置的对应的值来设置连接相关参数-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

7.5 mappers

​ 该标签的作用是加载映射的,加载方式有如下几种(主要使用第四种):

​ ①使用相对于类路径的资源引用,例如:

<!-- 使用相对于类路径的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>

​ ②使用完全限定资源定位符(URL),例如:

<!-- 使用完全限定资源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>

​ ③使用映射器接口实现类的完全限定类名,例如:

<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>

​ ④将包内的映射器接口实现全部注册为映射器,例如:

<!-- 定义dao接口所在的包。要求xml文件存放的路径和dao接口的包名要对应 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

此时对应包下所有xml映射文件都能找到
在这里插入图片描述

8. 打印日志

①log4j配置 在resources目录下创建log4j.properties文件:
 在Create resource bundle的弹出框中,在Resource bundel base name的输入框中填写资源文件的名称,不要带properties后缀,例如:validatemessage,其余都默认设置,点击OK按钮后就可以在resources文件夹中新增了一个validatemessage.properties文件

内容如下:

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout

②引入依赖

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

在这里插入图片描述
看这些是最重要的

9.获取参数时 #{}和${}的区别

​ 如果使用#{}.他是预编译的sql可以防止SQL注入攻击
​ 如果使用${}他是直接把参数值拿来进行拼接,这样会有SQL注入的危险

如果使用的是#{}来获取参数值日志如下:
Preparing: select * from user where id = ? and username = ? and age = ? and address = ?
Parameters: 2(Integer), 快乐风男(String), 29(Integer), 北京(String)

如果使用${}来获取参数值日志如下:
Preparing: select * from user where id = 2 and username = 快乐风男 and age = 29 and address = 北京

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值