Mybatis详解

Part 1

1.JDBC

1.1 JBDC执行流程
1.加载数据库驱动
2.创建并获取数据库连接
3.创建Statement
4.编写sql语句
5.设置查询参数
6.执行查询. 得到ResultSet对象
7.遍历ResultSet取查询结果
8.关闭流释放资源
1.2 模板
public static void main(String[] args) {
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultSet = null;
    try {
        //1. 加载数据库驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2. 通过驱动管理类获取数据库链接
        connection =  DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
        //3. 定义sql语句 ?表示占位符
        String sql = "select * from user where username = ?";
        //4. 获取预处理statement
        preparedStatement = connection.prepareStatement(sql);
        //5. 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
        preparedStatement.setString(1, "王五");
        //6. 向数据库发出sql执行查询,查询出结果集
        resultSet =  preparedStatement.executeQuery();
        //7. 遍历查询结果集
        while(resultSet.next()){
            System.out.println(resultSet.getString("id")+"  "+resultSet.getString("username"));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }finally{
        //释放资源
        if(resultSet!=null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        ......  
    }
}
1.3 JDBC有什么缺点?
数据库连接频繁创建, 效率低;
硬编码:
    数据库连接四个属性
    sql语句
    sql语句参数注入
    sal结果解析4.Mybatis

2.Mybatis : 持久层框架

2.1 Hibernate: ORM+数据库连接+session
O: 模型类
R: 关系型数据库的表
M: 映射(xxx.hbm.xml)
2.2 创建实体类: 注意字段应该和数据库中的表保持一致.
2.3 创建SqlMapConfig.xml配置文件
1. 配置数据库连接信息
2. 配置事务相关信息
<?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>
    <!--
        environments default="first": 选择那个environment
        transactionManager: 事务配置
        mappers: 加载映射关系表
    -->
    <!--配置连接池, 事务相关信息-->
    <environments default="first">
        <environment id="first">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="940114"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="User.xml"/>
    </mappers>
</configuration>
2.4 配置实体类映射文件
<?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">
<!--
    namespace: 命名空间,用于隔离sql语句
    id:
    parameterType: 传递的参数的类型
    resultType: 得到的数据的类型
-->
<mapper namespace="test">
    <!--1. 通过id查询用户-->
    <select id="findUserById" parameterType="int" resultType="domain.User">
        select * from user where id = #{id}
    </select>

    <!--2. 根据用户名查询用户信息, 查询到的结果是集合-->
    <!--<select id="findByUsername" parameterType="string" resultType="domain.User">
        select * from user where username like #{username}
    </select>

    <select id="findUsers" parameterType="string" resultType="domain.User">
        select * from user where username like "%${value}%"
    </select>-->

    <select id="findUsers1" parameterType="string" resultType="domain.User">
        select * from user where username like concat("%" , #{username}, "%")
    </select>

    <!--插入一条新的用户信息-->
    <insert id="saveUser" parameterType="domain.User">
        <selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER">
            select LAST_INSERT_ID()
        </selectKey>
        insert into user(username, birthday, sex, address) values(#{username}, #{birthday}, #{sex}, #{address})
    </insert>

    <!--删除数据-->
    <delete id="delUser" parameterType="int">
        delete from user where id = #{id}
    </delete>

    <!--修改用户-->
    <update id="updateUser" parameterType="domain.User">
        update user set username = #{username}, sex=#{sex}, birthday=#{birthday}, address=#{address} where id = #{id}
    </update>
</mapper>
2.5 测试文件
// 注意: SqlSessionFactory创建单例; sqlSession创建多例, 并且要及时关闭资源.
ublic class test {

    /**
     * sqlSessionFactory: 为单例
     * sqlSession: 为多例
     */
    //创建会话工厂
    private SqlSessionFactory sqlSessionFactory;
    //初始化ssf
    @Before
    public void initSSf() throws IOException {
        //加载配置文件
        String resource = "SqlMapConfig.xml";
        //加载配置文件的流
        InputStream is = Resources.getResourceAsStream(resource);
        //获取ssf
        SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
        // 初始化sqlSessionFactory
        sqlSessionFactory = ssfb.build(is);
    }

    /**
     * 通过id查询用户
     * @throws IOException
     */
    @Test
    public void select() throws IOException {
        /*//1. 加载配置文件
        String resource = "SqlMapConfig.xml";
        //2. 加载配置文件
        InputStream is = Resources.getResourceAsStream(resource);
        //3. 通过sqlSessionFactoryBuilder创建
        SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();
        //4. 创建sqlSession
        SqlSessionFactory sqlSessionFactory = sfb.build(is);
        //5. 执行查询方法*/
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("test.findUserById", 10);
        // 打印
        System.out.println(user);
        //6. 释放资源
        sqlSession.close();
    }

    /**
     * 通过用户名模糊查询
     * 1. 通过 #{username} 具体拼接在sqlSession中完成.
     * 2. 通过 ${value}.
     * 3. 通过concat(xx,xx,xx)进行拼接.
     */
    @Test
    public void findByUsername(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //List<User> users = sqlSession.selectList("findByUsername", "%" + "张" + "%");
        List<User> users = sqlSession.selectList("findUsers1", "张");
        for(User user : users){
            System.out.println(user);
        }
    }

    /**
     * 保存数据
     */
    @Test
    public void save(){
        // 创建user对象
        User user = new User();
        user.setUsername("orange");
        user.setAddress("长安区");
        user.setSex("1");
        user.setBirthday(new Date());

        // 向数据库保存用户
        SqlSession sqlSession = sqlSessionFactory.openSession();
        int insert = sqlSession.insert("test.saveUser", user);
        System.out.println(insert);
        sqlSession.commit();
        sqlSession.close();
    }

    /**
     * 删除数据
     */
    @Test
    public void del(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.delete("delUser", 32);
        sqlSession.commit();
        sqlSession.close();
    }

    /**
     * 更新用户数据
     */
    @Test
    public void update(){
        // 创建user对象
        User user = new User();
        user.setId(33);
        user.setUsername("orange");
        user.setAddress("荔枝湾");
        user.setSex("1");
        user.setBirthday(new Date());

        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.update("updateUser", user);
        sqlSession.commit();
        sqlSession.close();
    }
}
2.6 #{xxx} 和 ${value} 的区别
1. #{###}       : 相当于加上双引号, 相当于占位符
    将传入的数据都当作一个字符串, 会对自动传入的数据加上一个双引号;
2. ${value}    : 相当于直接显示数据, 相当于拼接sql串
    将传入的数据直接显示生成在sql中.
3. 联系和区别???
    1) 方式可以很大程度上防止sql注入;
    2) $方式无法防止sql注入, $方式一般用于传入数据库对象(数据库列名)
    3) 能用# 就不用 $
2.7 mysql自增主键返回
<!--插入一条新的用户信息-->
<insert id="saveUser" parameterType="domain.User">
    <selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER">
        select LAST_INSERT_ID()
    </selectKey>
        insert into user(username, birthday, sex, address) values(#{username}, #{birthday}, #{sex}, #{address})
</insert>
<!--
    注意当数据库表的主键字段设置为自增的时候, 这个时候order就要设置为 AFTER;
    数据库表中主键的字段为自动设置的时候, 这时候的order就要设置为before;
-->

3.dao的编写

3.1 传统dao的编写
// UserDaoImpl
public class UserDaoImpl implements UserDao {

    // 注入sessionFactory
    private SqlSessionFactory sqlSessionFactory;

    public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    @Override
    public User findById(int id) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = null;
        try {
            user = sqlSession.selectOne("findUserById", 33);
            System.out.println(user);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sqlSession.close();
        }
        return user;
    }
}
// Test
public class test {
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void initSSFB() throws IOException {
        //1. 读取配置文件
        String resource = "SqlMapConfig.xml";
        //2. 获取读取文件的流
        InputStream is = Resources.getResourceAsStream(resource);
        //3. 获取对象
        SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
        sqlSessionFactory = ssfb.build(is);
    }

    @Test
    public void get(){
        UserDao userDao = new UserDaoImpl(sqlSessionFactory);
        userDao.findById(33);
    }
}

3.2 Mapper动态代理方式(JDK动态代理)
编写规则:
1. Mapper.xml文件中的namespace与mapper接口的类路径相同。
2. Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
3. Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
4. Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
3.3 Mapper接口编写
package Mapper;
import domain.User;
public interface Mapper {
    User findUserById(int id);
    void insertUser(User user);
}
3.4 Mapper配置文件编写
<?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">
<!--
    namespace: 为接口的全类名
    id: 需要和接口中的方法名保持一致
    parameterType, resultType 要和方法中的参数, 返回值保持一致.
-->
<mapper namespace="Mapper.Mapper">
    <select id="findUserById" parameterType="int" resultType="domain.User">
        select * from user where id = #{username};
    </select>

    <insert id="insertUser" parameterType="domain.User">
        <selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER">
            select LAST_INSERT_ID()
        </selectKey>
        insert into user(username, birthday, sex, address) values(#{username}, #{birthday}, #{sex}, #{address})
    </insert>
</mapper>
3.5 测试类编写
public class test {

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws IOException {
        //加载配置文件
        String resource = "SqlMapConfig.xml";
        InputStream is = Resources.getResourceAsStream(resource);
        SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
        sqlSessionFactory = ssfb.build(is);
    }

    // 这里直接调用getMapper方法, 获取代理类对象
    @Test
    public void search(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        Mapper mapper = sqlSession.getMapper(Mapper.class);
        User user = mapper.findUserById(33);
        System.out.println(user);
        sqlSession.close();
    }
}

Part 2

1.利用包装类完成查询
1.1 包装类的实体类: 结合聚合函数通常返回
public class QueryVo {
    private User user;
    public void setUser(User user) {
        this.user = user;
    }
    public User getUser() {
        return user;
    }
}
1.2 映射文件的配置
<?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">
<!--
    namespace: 为接口的全类名
    id: 需要和接口中的方法名保持一致
    parameterType, resultType 要和方法中的参数, 返回值保持一致.
    resultType: 中的user是通过 typeAlias起的别名
-->
    <!--通过包装类进行查询-->
    <select id="getUserByQueryVo" parameterType="queryvo" resultType="user">
        select * from user where id = #{user.id}
    </select>
</mapper>
1.3 解决数据库表和实体类字段不对应方法
1. 第一种: sql语句利用起别名的方式解决字段不一致问题.
<!--2. 利用resultMap的方式.-->
<?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">
<!--
    namespace: 为接口的全类名
    id: 需要和接口中的方法名保持一致
    parameterType, resultType 要和方法中的参数, 返回值保持一致.
-->
<mapper namespace="Mapper.OrderMapper">
    <!--查询所有的order-->
    <!--<select id="getOrderList" resultType="orders">
        SELECT id, user_id userId, number, createtime, note FROM orders
    </select>-->
    <!--
        1. type: 对应的是结果映射的pojo类
        2. property: 实体类中的字段. column: 对应表中字段的名称
    -->
    <resultMap id="order_list_result" type="orders">
        <!--主键-->
        <id property="id" column="id"/>
        <!--普通列-->
        <result property="userId" column="user_id"/>
        <result property="number" column="number"/>
        <result property="createtime" column="createtime"/>
        <result property="note" column="note"/>
    </resultMap>
    <!--查询所有的order-->
    <select id="getOrderList" resultMap="order_list_result">
        select * from orders
    </select>
</mapper>
2.动态生成sql语句
2.1 if(判断), where解决了第一个and出现的问题
<!--动态生成sql语句-->
<select id="getUserByUser" parameterType="user" resultType="user">
    select * from user
    <where>
        <if test="id != 0">
            and id = #{id}
        </if>
        <if test="username != null and username != ''">
            and username = #{username}
        </if>
    </where>
</select>
2.2 foreach遍历
<!--
        foreach的动态生成sql
        collection : 表示要循环遍历的集合或数组
        item : 每次遍历得到的元素
        open : 循环开始之前添加的内容  只执行一次
        close : 循环结束之后添加的内容 只执行一次
        separator : 每循环一次就执行一次
    -->
    <!--select * from user where id in (1,2,3)-->
    <select id="getUserInIds" parameterType="queryvo" resultType="user" >
        select * from user
        <where>
            <foreach collection="ids" item="id" open="and id in (" close=")" separator=",">
                #{id}
            </foreach>
        </where>
    </select>
2.3 set的使用
<!--
        更新操作
        update user set username = ?, password = ? where id = ?
        set: 解决了最后一个逗号出现的问题
    -->
    <update id="updateUser" parameterType="user">
        update user
            <set>
                <if test="username != null and username != ''">
                    username = #{username},
                </if>
                <if test="address != null and address != ''">
                    address = #{address},
                </if>
            </set>
        where id = #{id}
    </update>
3.动态生成sql语句
<!--
     动态生成sql片段
 -->
<sql id="set_username_address">
    <set>
        <if test="username != null and username != ''">
            username = #{username},
        </if>
        <if test="address != null and address != ''">
            address = #{address},
        </if>
    </set>
</sql>
4.一对一关联映射
4.1 创建一个pojo类, 属性为sql查询结果的字段.
<!--
    一对一, 关联映射查询.orderUser为新建的po类
-->
<select id="findOrderAndUser" resultType="orderUser">
    SELECT
    o.*, u.username, u.address
    FROM
    orders o
    LEFT JOIN user u ON u.id = o.user_id
</select>
4.2 利用resultMap
<!--
    第一步: 在orders实体类中持有对user类的引用
    第二步: 配置映射文件, 主要配置resultMap;
    注意: 一对一关联映射使用的标签为 association
-->
<resultMap id="order_user_result_map" type="orders">
    <!-- 主键 -->
    <id property="id" column="id"/>
    <!--普通列-->
    <result property="userId" column="user_id"/>
    <result property="number" column="number"/>
    <result property="createtime" column="createtime"/>
    <result property="note" column="note"/>
    <!-- 一对一关联映射 -->
    <association property="user" javaType="domain.User">
        <id property="id" column="user_id"/>
        <result column="username" property="username"/>
        <result column="address" property="address"/>
    </association>
</resultMap>
<select id="findOrderAndUser" resultMap="order_user_result_map">
    SELECT
    o.*, u.username, u.address
    FROM
    orders o
    LEFT JOIN user u ON u.id = o.user_id
</select>
5.一对多关联映射查询
<!--
        一对多关联映射查询
        ofType : 代表一对多的关联映射
    -->
    <resultMap id="user_orders_result" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
        <!-- 一对多关联映射 -->
        <collection property="orders" ofType="domain.Orders">
            <id property="id" column="oid"/>
            <result property="number" column="number"/>
            <result property="createtime" column="createtime"/>
        </collection>
    </resultMap>
    <select id="findUserAndOrders" resultMap="user_orders_result">
        SELECT
            u.*,
            o.id oid,
            o.number,
            o.createtime
        FROM
            `user` u
            LEFT JOIN orders o ON u.id = o.user_id
    </select>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值