MyBatis个人笔记(1.2版本)

MyBatis

  1. mybatis优势
    mybatis与jdbc、hibernate的对⽐:

jdbc:代码⽐较多,开发效率低,重复代码多,业务代码和数据库操作混杂⼀起。在代码块中对象要创建和销毁,查询的结果要封装 list。

hibernate:全⾃动

mybatis:提供访问数据库基本功能,半⾃动,sql与java编码分离,轻量级的框架

一、Mybatis介绍

MyBatis是一个支持普通SQL查询存储过程高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。

img

二、mybatis快速入门

1.1 准备开发环境

  1. 创建普通java项目或者是JavaWeb项目
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EZ5xGAgG-1658994074151)(C:\Users\飞\AppData\Roaming\Typora\typora-user-images\image-20220725191226711.png)]

  2. 添加相应的jar包
    在这里插入图片描述

在这里插入图片描述

  1. 创建数据库
  2. 配置 MyBatis
    配置 MyBatis 有多种方式,使用最基础最常用的 XML 形式进行配置

使用 XML 形式进行配置,首先在 src/main/resourc es 下面创建 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 >
    <!--    log4j日志组件的使用-->
    <properties resource="db.properties">
    </properties>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true" />
        <setting name="logImpl" value="STDOUT_LOGGING" />
        <setting name="useGeneratedKeys" value="true"/>
    </settings>
    <typeAliases>
<!--        <typeAlias type="com.qq.model.Book" alias="Book"/>  -->
        <package name="com.qq.model"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <!-- 配置数据库连接信息 -->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/shop?serverTimezone=Hongkong&amp;useSSL=false&amp;characterEncoding=utf-8&amp;useUnicode=true" />
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
         <!--<mapper resource="com/qq/mapper/BookMapper.xml"></mapper>-->
         <!--<mapper class="com.qq.mapper.BookMapper"></mapper>-->
         <!--<mapper url="file:///E:\HQYJ\studyMybatis\src\com\qq\mapper\BookMapper.xml"></mapper>-->
        <package name="com.qq.mapper"/>
    </mappers>

</configuration>
Mybatis 核心配置文件解析
 <?xml version="1.0" encoding="UTF-8" ?>

<?xml ?>:报文头格式,报文头内容放在xml和?符号中间

version="1.0":声明使用的xml版本

encoding="utf-8":声明用xml传输数据时候用的字符编码(字符集)

验证文档:<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
在全集配置文件中引入dtd约束“http://mybatis.org/dtd/mybatis-3-config.dtd”


根节点是<configuration>:
 Configuration类的位置org.apache.ibatis.session.Configuration
Configuration类保存了所有Mybatis的配置信息。
一般情况下Mybatis在运行过程中只会创建一个Configration对象,并且配置信息不能再被修改。
Configuration的属性
configuration的属性主要分为两大部分:
1. 从mybatis-config.xml中读取的配置
2. 从mapper配置文件或Mapper注解读取的配置
    
可选的properties节点:
properties属性----引入外部properties配置文件
    可以使用properties节点来指定.properties文件,那么后面在很多需要的地方,就可以用${xxx}的形式从.properties文件中取值。这样的好处是可以把重要、独立、机密的一些值统一放到.properties文件中,便于管理。
我们把配置文件中基础信息单独写在db.properties文件中
    <properties resource="db.properties">           //指定文件
	<property name="db.username" value="root"/>   //也可以在这里传值
	<property name="db.password" value="123456"/>
     </properties>
注意一个问题:
在配置文件中,url 路径中有 & 符号,会使用 &amp; 来代替,当我们把url抽离出来,放到xxx.properties 文件中时,需要把  &amp; 改成 & 。

<settings> 中的 ogimp 属性配置指定使用 LOG4J 输出日志
    cacheEnabled
    lazyLoadingEnabled
    logImpl
 
类名别名(typeAliases)
   如果嫌有时写类型名太长,比如上面的查询结果类型resultType="com.qq.model.Book"的名写着太长,可以使用类型别名方式,这要在基本配置文件中使用<typeAliases>指定。
    <typeAliases>
        以使用类型别名方式,这要在基本配置文件中使用<typeAliases>指定。
        方式一:<!--<typeAlias type="com.qq.model.Book" alias="Book"/>  -->
        这样我们后面在映射文件中就可以写成resultType="Book"了
        方式二:也可以使用一个包名
        <package name="com.qq.model"/>
    </typeAliases>
    
<environments>环境 配置中 主要 配置了数据库连接,数据库的 url
jdbc:mysql://localhost:3306/mybatis ,使用的是本机 MySQL 中的 mybatis
数据库,后面的 username password 分别是数据库的用户名和密码(如果你的数据库用户名及密码和这里的不 样,请修改为自己数据库可用的用户名和密码〉   
    <environments default="development">
	<environment id="development">
		<transactionManager type="JDBC" />
		<!-- 配置数据库连接信息 -->
		<dataSource type="POOLED">
			<property name="driver" value="com.mysql.jdbc.Driver" />
			<property name="url" value="jdbc:mysql://localhost:3306/lib?characterEncoding=utf-8" />
			<property name="username" value="root"/><property name="username" value="${db.username}"/>
			<property name="password" value="123456" /><property name="password" value="${db.password}" />
		</dataSource>
	</environment>
</environments>

<mappers></mappers>中配置了 个包含完整类路径的 CountryMapper.xml ,这是 MyBatis
SQL 语句和映射配置文件  
  最常用的配置:
<!--每一个Mapper.xml(sql映射文件)都需要在Mybatis核心文件中注册!-->
<mappers>
    <mapper resource="com/lxc/dao/UserMapper.xml"></mapper>
</mappers>
Mybatis中mappers的映射配置:
    一、通过resource加载单个映射文件:
      1.通过<mapper resource=""/>
  <mappers>
    <mapper resource="mapper/UserMapper.xml"/>
</mappers>
      2.通过<mapper url=""/>
    <mappers>
    <mapper url="D:\myeclipse\word\mybatis\config\mapper\UserMapper.xml"/>    
</mappers>
    3.通过mapper接口加载
    <!--  需要将mapper接口类名和mapper.xml映射文件名称保持一致且在同一个目录中,
     注意:要使用的是mapper代理。两个文件要在同一个目录  -->
<mappers>
    <mapper class="dancheng.mybatis.mapper.UserMapper"/>
</mappers>
    二、批量加载
    指定mapper接口包名
    <!--  需要将mapper接口类名和mapper.xml映射文件名称保持一致且在同一个目录中,
     注意:要使用的是mapper代理。两个文件要在同一个目录    -->
<mappers>
    <package name="dancheng.mybatis.mapper"/>
</mappers>
    
    在数据库中,由于大多数数据库设置不区分大小写 ,因此下画线方式的命名很常见,如
user name user email 。在 Java 中, 般都使用驼峰式命名,如 userName userEmail
因为数据库和 Java 中的这两种命名方式很常见,因此 MyBatis 还提供 个全局属性
mapUnderscoreToCamelCase ,通过配置这个属性为 true 可以自动将以下画线方式命名的
数据库列映射到 Java 对象的驼峰式命名属性中。这个属性默认为 false ,如果想要使用该功能,
需要在 MyBatis 的配置文件(mybatis-config.xml 文件)中增加如下配置。
    <settings>
	<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
    如果使用了这个驼峰转换,在查询select数据时可以进行智能的匹配(以便得到的字段值填入实体类对象成员),但是在插入insert和修改update数据时不能智能匹配(此时必须给出类中成员的真名)

根节点内的子节点的顺序是固定的:
The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)".

2.2 用mybatis去访问数据库的三种编码方式

(一)xml映射文件 + sqlSession调用相应的方法

框架已经设计了多个方法供使用,如selectOne(statement,id),该statement是“命名空间与映射文件中的id组成的字符串”,则就运行起sql语句了(此方式已过时,但常作为入门写法学习)。(这是直接执行id号的感觉,也可以往里面传输丰富的参数值,得到的对象也是指定了类型)

  1. 定义操作Book表的sql映射文件BookMapper.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.qq.mapper.BookMapper">
    
        <select id="selectOne" parameterType="int" resultType="com.qq.model.Book" >
            select * from book where id=#{id}
        </select>
    
        <select id="selectAll" resultType="Book" >
            select * from book
        </select>
    
        <insert id="insertOne"  keyProperty="id" parameterType="com.qq.model.Book">
    <!--        <selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="int">-->
    <!--            SELECT LAST_INSERT_ID()-->
    <!--        </selectKey>-->
            insert into book (name,author,price)
            values (#{name},#{author},#{price})
        </insert>
        <insert id="insertOne2">
            insert into book (name,author,price)
                values (#{name},#{author},#{price})
        </insert>
        <insert id="insertOne3" >
            insert into book (name,author,price)
            values (#{name},#{author},#{price})
        </insert>
        <update id="modify" parameterType="com.qq.model.Book">
            update book
            set name=#{name},
                <if test="author!=null and author!=''">
                    author=#{author},
                </if>
            price=#{price} where id=#{id}
        </update>
        <delete id="deleteById" >
            delete from book
            where id=#{id}
        </delete>
    
        <select id="selectByName" parameterType="String" resultType="com.qq.model.Book" >
            select * from book where name like #{name}
        </select>
        <select id="selectByName2" parameterType="String" resultType="com.qq.model.Book" >
            select * from book where name like '%#{name}%'
        </select>
        <select id="selectByName3" parameterType="String" resultType="com.qq.model.Book" >
            select * from book where name like concat( '%',#{name} , '%')
        </select>
        <select id="selectByName4" parameterType="String" resultType="com.qq.model.Book" >
            select * from book where name like '%${value}%'
        </select>
        <select id="queryOrder" parameterType="string" resultType="com.qq.model.Book">
    
            select * from book order by CONVERT(${value} USING gbk)
    
        </select>
        <select id='queryOrder1' parameterType='string' resultType='com.qq.model.Book'>
            select * from book where  lower(name)  LIKE  lower('%${value}%')
        </select>
    
    
    
    
    </mapper>
    
    

    MySQL 定义在 BookMapper.xml 文件中,里面的配置作用如下:

    • XML 的根元素 属性 ηamespace 定义了当 XML 的命名 空间。

    • <select >元素 :我们所定义的一个 SELECT 查询。
      
    • id 属性:定义了当前 SELECT 查询的唯一一个id

    • resultType :定义了当前查询的返回值类型

    • select id, …: 查询 SQL 语句。

    • parameterType:该参数只表示一个参数类型,其中@Param和parameterType 二者存其一即可

  2. 编写测试

package com.qq;

import com.qq.model.Book;
import com.qq.util.MybatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

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

/**
 * @description:com.qq_studyMybatis
 * @author: 霏宇
 * @time: 2022/7/24,15:48
 * (一)xml映射文件  + sqlSession调用相应的方法
 */
public class MyTest1 {
    public static void main(String[] args) {


       SqlSession  session = MybatisUtil.getSqlSession();
       List<Book> books= session.selectList("com.qq.mapper.BookMapper.selectAll");
        for (Book one : books) {
            System.out.println(one.toString());

        }
        String statement1 = "com.qq.mapper.BookMapper.selectOne";
        Book book = session.selectOne(statement1, 1); // 隐式强转
        System.out.println(book.toString());


        String statement="com.qq.mapper.BookMapper.insertOne";
        Book book1 =new Book();
        book1.setName("最丑的男人");
        book1.setAuthor("2");
        book1.setPrice(5.0);

        int num = session.insert(statement,book1);
        System.out.println("受影响的行数=" + num);
        session.commit();//一定要有这句
        session.close();

        for (Book one : books) {
            System.out.println(one.toString());

        }
    }
}

(二)xml映射文件 + java接口方式

Xml文件中的sql语句,和java接口中的方法相对应。

sqlSession可以获取接口对象,(接口能被框架实例化出类对象),然后利用这个对象调其中的方法。

这种方式要多写一个接口Interface以及其中的抽象方法。此方式整体功能强大,是目前最多使用的方式。

这种方式的有个必须满足的要求就是Mapper.xml文件的根标签的namespace属性的值需要写成接口的全限定名。虽然,XxxxMapper.xml与XxxxMapper.java是可以放置在不同的文件夹下面,不过呢,笔者一般是把.java接口文件和xml文件并列放在挨在一起的,这行都这样做。

BookMapper接口文件代码:

package com.qq.mapper;
import com.qq.model.Book;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
 * @description:com.qq.mapper_studyMybatis
 * @author: 霏宇
 * @time: 2022/7/25,9:17
 *
 */
public interface BookMapper {
     List<Book>selectAll();
     Book selectOne(int id);
     int  insertOne(Book book);
//     int insertOne2(String name ,String author,double price);//values (#{arg0},#{arg1},#{arg2})
     //使用索引:Mybatis3.4版本已改为用#{arg0},#{arg1}
     int insertOne2(@Param("name") String name ,@Param("author") String author, @Param("price") double price);

     int insertOne3(Map map);
     int modify(Book book);
     int deleteById(int id);
     List<Book>selectByName(String name);
     List<Book>selectByName2(String name);
     List<Book>selectByName3(String name);
     List<Book>selectByName4(String name);
     List<Book> queryOrder(String column);
     List<Book> queryOrder1(String name);
}

测试类:

package com.qq;

import com.qq.mapper.BookMapper;
import com.qq.mapper.BookMapper3;
import com.qq.model.Book;
import com.qq.util.MybatisUtil;
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.io.Reader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description:com.qq_studyMybatis
 * @author: 霏宇
 * @time: 2022/7/25,9:23
 * (二)xml映射文件 + java接口方式
 */
public class MyTest2 {
    public static void main(String[] args) throws IOException {
        //创建session并获取工厂

        //获取工厂法一:字符输入流
//        Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//        SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader);

        //获取工厂法二:字节输入流
//        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//        SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(is);

        //利用工厂打开会话
//        SqlSession sqlsession= sessionFactory.openSession();


        SqlSession  sqlsession = MybatisUtil.getSqlSession();
        //获取mapper接口的实例
        BookMapper bookMapper = sqlsession.getMapper(BookMapper.class);//这句是关键
        //用mapper调相应方法

        //通过id获取书籍信息
        System.out.println("通过id获取书籍信息");
        System.out.println("--------------------------------------------------------------------------------------");
        Book book = bookMapper.selectOne(2);
        if(book!=null) System.out.println("书籍信息="+book.toString());

        List<Book> list = bookMapper.getAll();
		for(Book one:list){
			System.out.println("用户信息="+one.toString());
		}
  
         sqlsession.close();//一定不要忘记close(),否则数据库连接过多会导致系统崩溃
    }
}

:上面代码不涉及到sqlSession.commit()语句,因为都是查询。如果做的是数据写操作insert、update、delete,则往往需要显式提交即sqlSession.commit()的。

(三)接口 + 注解的方式

它是将sql语句直接写在java代码的方法上。暂时不建议使用这种方式(将来可能会比较流行)。

这种方式不需要xml文件,sql语句直接写在java接口的方法注解上。如下

package com.qq.mapper;

import com.qq.model.Book;
import org.apache.ibatis.annotations.Select;

/**
 * @description:com.qq.mapper_studyMybatis
 * @author: 霏宇
 * @time: 2022/7/25,10:32
 */
public interface BookMapper3 {
    @Select("Select * From book Where id= #{id}")
    public Book selectById(int id) ;


}

编写一个MybatisUtil

可以把SqlSession的获取放到一个单独的工具类里面,如MybatisUtil,以后每次要使用时就从里面去拿

package com.qq.util;

import com.qq.MyTest1;
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;

/**
 * @description:com.qq.util_studyMybatis
 * @author: 霏宇
 * @time: 2022/7/25,10:03
 */
public class MybatisUtil {
     private  static SqlSessionFactory factory =null;
    static {
        String resource = "mybatis-config.xml";

        try {
            InputStream is  = Resources.getResourceAsStream(resource);
             factory=new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    public MybatisUtil() {
    }

     public static SqlSession getSqlSession(){
        return  factory.openSession();

    }
}

编写一个DBUtil

这仅仅是一个单例方式的功能实现,不追求性能

package com.qq.util;

import java.sql.*;

/**
 * @description:com.qq_studyMybatis
 * @author: 霏宇
 * @time: 2022/7/24,9:55
 */
public class DBUtil {
    private static  Connection con=null;
    private static String driver = "com.mysql.jdbc.Driver";
    private static String url = "jdbc:mysql://localhost:3306/shop?serverTimezone=Hongkong&useSSL=false&characterEncoding=utf-8&useUnicode=true";
    private static String user = "root";
    private static String password = "XXXXXX";

    //静态块: 一旦当前类被使用,那么静态块就会被执行一次块
    static {
           try {
               Class.forName(driver);//""com.mysql.cj.jdbc.Driver
           }catch (ClassNotFoundException e){
               e.printStackTrace();

               }
           }
    //防止被new
    private  DBUtil(){

    }
     public static Connection getConnection(){
        try {
            if(con!=null){
                if(!con.isClosed())//判断连接是否已被关闭。因为con.close()就可以关闭
                    return con;
                else {
                    con = DriverManager.getConnection(url,user,password);
                    return con;
                }
            }
            else {
                con = DriverManager.getConnection(url,user,password);
                return con;
            }

        } catch (SQLException e){
            e.printStackTrace();
            return con;
        }
    }
    // 关闭ResultSet
    public static void close(ResultSet rs) {
        if (rs != null)
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
    }
    // 关闭Statement
    public static void close(Statement stmt) {
        if (stmt != null)
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
    }
    // 关闭PreparedStatement

    public static void close(PreparedStatement pstmt) {
        if (pstmt != null)
            try {
                pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
    }

    // 关闭Connection
    public static void close(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }




}

编写最简单的数据库DBPool

package com.qq.util;

import java.sql.*;

/**
 * @description:com.qq_studyMybatis
 * @author: 霏宇
 * @time: 2022/7/24,11:13
 */
public class DBPool {
    private static  Connection con=null;
    private static String driver = "com.mysql.jdbc.Driver";
    private static String url = "jdbc:mysql://localhost:3306/shop?serverTimezone=Hongkong&useSSL=false&characterEncoding=utf-8&useUnicode=true";
    private static String user = "root";
    private static String password = "XXXXXX";

    private static Connection[] cons = new Connection[10];
    private static int count = 0;  //计数器,代表当前轮到第几个连接提供服务了
    static {
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        //这里不要用foreach,它会无效,详见https://blog.csdn.net/weixin_42247720/article/details/80460975
//        try {
//            for (Connection one : cons) {
//                one=DriverManager.getConnection(url, user, password);
//
//
//            }
//        }catch (SQLException e){
//            e.printStackTrace();
//        }

        for(int i=0; i<cons.length; i++) {
            try {
                cons[i] = DriverManager.getConnection(url, user, password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }


    }

    private DBPool() {}

    public static Connection getConnection(){
        //在cons[] 里面拿一个就行
        count ++;
        if (count>=10) count=0;
        System.out.println(count);
        System.out.println(count%10);
        return cons[count]; //0,1,2,3.....9

    }


}

3.3 select 用法

使用纯粹 JDB 时,需要写查询语句,并且对结果集进行手动处理 将结果映 到对象的属 性中。使用 My at 时,只 需要在 XM 中添加 select 元素,写 SQL 再做 些简 单的配置,就可以将查询的结果直接映射到对象中

查询select(包括查询出一条selectOne和查询全部selectAll)
  1. 在 BookMapper 接口中添加一个 selectOne和selectAll方法

    package com.qq.mapper;
    
    import com.qq.model.Book;
    import org.apache.ibatis.annotations.Param;
    import java.util.List;
    /**
     * @description:com.qq.mapper_studyMybatis
     * @author: 霏宇
     * @time: 2022/7/25,9:17
     *
     */
    public interface BookMapper {
         List<Book>selectAll();
         Book selectOne(int id);
        
    }
    
    
  2. 在对应 BookMapper .xml 添加如下的< select >部分的代码。

<?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.qq.mapper.BookMapper">

    <select id="selectOne" parameterType="int" resultType="com.qq.model.Book" >
        select * from book where id=#{id}
    </select>

    <select id="selectAll" resultType="Book" >
        select * from book
    </select>
</mapper>
resultMap :用于设置返回值的类型和映射关系

3.在测试类运行

package com.qq;

import com.qq.mapper.BookMapper;
import com.qq.mapper.BookMapper3;
import com.qq.model.Book;
import com.qq.util.MybatisUtil;
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.io.Reader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description:com.qq_studyMybatis
 * @author: 霏宇
 * @time: 2022/7/25,9:23
 * (二)xml映射文件 + java接口方式
 */
public class MyTest2 {
    public static void main(String[] args) throws IOException {
        //创建session并获取工厂

        //获取工厂法一:字符输入流
//        Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
//        SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader);

        //获取工厂法二:字节输入流
//        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//        SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(is);

        //利用工厂打开会话
//        SqlSession sqlsession= sessionFactory.openSession();


        SqlSession  sqlsession = MybatisUtil.getSqlSession();
        //获取mapper接口的实例
        BookMapper bookMapper = sqlsession.getMapper(BookMapper.class);//这句是关键
        //用mapper调相应方法

        //通过id获取书籍信息
        System.out.println("通过id获取书籍信息");
        System.out.println("--------------------------------------------------------------------------------------");
        Book book = bookMapper.selectOne(2);
        if(book!=null) System.out.println("书籍信息="+book.toString());

        //查询所有书籍信息
        System.out.println("--------------------------------------------------------------------------------------");
        System.out.println("查询所有书籍信息");
          List<Book> books =bookMapper.selectAll();
        for (Book book1 : books) {
            System.out.println(book1.toString());

        }


    }
}
parameterType:指的是传入参数的类型。
resultType:指得到的数据的类型,它应是java包中的一个具体类的全限定名。

模糊查询解决方案

错误的写法:

 <select id="selectByName2" parameterType="String"resultType="com.qq.model.Book" >
        select * from book where name like '%#{name}%'
    </select>

由于#号会在底层转化为?占位符的形式,相当于select * from book where name like ‘%?%’,数据库没法处理。

方法一:用函数concat()进行拼接

xml为:

<select id="selectByName3" parameterType="String" resultType="com.qq.model.Book" >
        select * from book where name like concat( '%',#{name} , '%')
    </select>

测试类:

System.out.println("用户模糊查询法一:用函数concat()进行拼接");

        List<Book> name =bookMapper.selectByName3("成");
        for (Book book1 : name) {
            System.out.println(book1.toString());

        }
方法二:让调用方传入的参数本身必须含%符号

xml为:

 <select id="selectByName" parameterType="String" resultType="com.qq.model.Book" >
        select * from book where name like #{name}
    </select>

测试类:

 System.out.println("用户模糊查询法二:让调用方传入的参数本身必须含%符号");
        List<Book> name2 =bookMapper.selectByName("%成%");
        for (Book book1 : name2) {
            System.out.println(book1.toString());

        }
方法三:使用$符号

xml为:

 <select id="selectByName4" parameterType="String" resultType="com.qq.model.Book" >
        select * from book where name like '%${value}%'
    </select>

测试类:

  /*
        #和$的区别:
        1 #表示sql模板的占位符,$表示将字符串拼接到sql模板中。
        2 #可以防止sql注入,一般能用#就不用$。
        3 ${}内部的参数名必须写value。
         */
System.out.println("用户模糊查询法三:使用$符号");
        List<Book> name3 =bookMapper.selectByName4("%成%");
        for (Book book1 : name3) {
            System.out.println(book1.toString());

        }

3.4 增、删、改三种操作

插入过程中获取主键自增值(如何获取生成的主键)
第一种方式是使用useGeneratedKeys + keyProperty组合的方式

xml文件对应sql如下

其中userGeneratedKeys代表是告诉mybatis要使用自增生成的主键,keyProperty是告诉mybatis主键字段是哪个,如下:

//有自增功能的表
<insert id="insertOne"  keyProperty="id" parameterType="com.qq.model.Book"  useGeneratedKeys="true">
        insert into book (name,author,book_price)
        values (#{name},#{author},#{price})
    </insert>

或者在mybatis的全局配置文件中设置。但这会影响所有的insert语句

//有自增功能的表
<settings>
	<setting name="useGeneratedKeys" value="true"/>
</settings>
那么此时的insert语句可以省略掉useGeneratedKeys="true",如
<insert id="add" keyProperty="id">
     insert into book (name,author,book_price)
        values (#{name},#{author},#{price})
</insert>

第二种方式是通过来指定sql语句获取生成的主键ID

这种方式通过selectKey标签来设置通过哪种方式生成主键,目前只支持通过执行一个sql语句来生成主键值如select UUID(),可能配置如下:

<insert id="insertByQueryParamter" parameterMap="myParameterMap">
    <selectKey keyProperty="id" keyColumn="id"
               resultType="int" order="BEFORE">
        select uuid()
    </selectKey>
      insert into book (name,author,book_price)
        values (#{name},#{author},#{price})
</insert>
//BEFORE是由于oracle是先生成序列值而后插入

第三种方式:这只针对一些不支持自增的数据库,如oracle
<insert id="add">
	<selectKey resultType="java.lang.Integer" order="BEFORE" keyProperty="id">
		select seq.nextval as id from dual
	</selectKey>
	insert into users (id,name,age) values(#{id},#{name},#{age})
</insert>
//BEFORE是由于oracle是先生成序列值而后插入
//seq是自定义的序列名, nextval是oracle的语法代表下一个的意思, dual是一个虚表
第四种方式:有些数据库的函数能够支持提取刚刚自增的值,如mysql的SELECT LAST_INSERT_ID()

xml文件对应sql如下

//这只针对一些不支持自增的数据库,如oracle
<insert id="insertOne"  keyProperty="id" parameterType="com.qq.model.Book">
  <selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="int">
           SELECT LAST_INSERT_ID()
       </selectKey>
        insert into book (name,author,book_price)
        values (#{name},#{author},#{price})
    </insert>
具体解释:
SELECT LAST_INSERT_ID():得到刚 insert 进去记录的主键值,只适用与自增主键
keyProperty:将查询到主键值设置到 parameterType 指定的对象的那个属性
order:SELECT LAST_INSERT_ID() 执行顺序,相对于 insert 语句来说它的执行顺序
resultType:指定 SELECTLAST_INSERT_ID() 的结果类型
多参数解决方案

要解决“接口各参数”和“sql中的占位符”的对应关系,有三种方案

(1)方案一:使用索引,sql中按照参数的顺序,从0开始。

xml:

<insert id="insertOne1">
        insert into book (name,author,book_price)
          values (#{arg0},#{arg1},#{arg2})
    </insert>

BookMapper接口:

int insertOne1(String name ,String author,double price);

测试类·:

int number=bookMapper.insertOne1("s3333b","1",510.0);

(2)方案二:使用map对象

xml:

 <insert id="insertOne2" >
        insert into book (name,author,book_price)
        values (#{name},#{author},#{book_price})
    </insert>

BookMapper接口:

int insertOne2(Map map);

测试类·:

       System.out.println("传递多个参数方法三:使用map对象");
       Map map =new HashMap<String, String>();
       map.put("name","差异化");
       map.put("author","差异化");
       map.put("price","111");
       int number=bookMapper.insertOne2(map);
       System.out.println("添加结果"+number);

(3)方案三

xml:

 <insert id="insertOne3">
        insert into book (name,author,book_price)
            values (#{name},#{author},#{book_price})
    </insert>

BookMapper接口:

int insertOne3(@Param("name") String name ,@Param("author") String author, @Param("price") double price);

测试类·:

int number=bookMapper.insertOne2("s3333b","一生",510.0);
Update

xml文件对应sql如下

 <update id="modify" parameterType="com.qq.model.Book">
        update book
        set name=#{name},
            <if test="author!=null and author!=''">
                author=#{author},
            </if>
        book_price=#{bookPrice} where id=#{id}
    </update>

BookMapper:

int modify(Book book);
delete

xml文件对应sql如下

<delete id="deleteById" >
        delete from book
        where id=#{id}
    </delete>

BookMapper:

int deleteById(int id);

");
map.put(“price”,“111”);
int number=bookMapper.insertOne2(map);
System.out.println(“添加结果”+number);


(3)方案三

xml:

```xml
 <insert id="insertOne3">
        insert into book (name,author,book_price)
            values (#{name},#{author},#{book_price})
    </insert>

BookMapper接口:

int insertOne3(@Param("name") String name ,@Param("author") String author, @Param("price") double price);

测试类·:

int number=bookMapper.insertOne2("s3333b","一生",510.0);
Update

xml文件对应sql如下

 <update id="modify" parameterType="com.qq.model.Book">
        update book
        set name=#{name},
            <if test="author!=null and author!=''">
                author=#{author},
            </if>
        book_price=#{bookPrice} where id=#{id}
    </update>

BookMapper:

int modify(Book book);
delete

xml文件对应sql如下

<delete id="deleteById" >
        delete from book
        where id=#{id}
    </delete>

BookMapper:

int deleteById(int id);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值