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. 配置事务相关信息


<configuration>
    
    
    <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 配置实体类映射文件



<mapper namespace="test">
    
    <select id="findUserById" parameterType="int" resultType="domain.User">
        select * from user where id = #{id}
    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 users = sqlSession.selectList("findByUsername", "%" + "张" + "%");
        List 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>

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配置文件编写
"1.0" encoding="UTF-8" ?>
"-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

"Mapper.Mapper">
    

    "insertUser" parameterType="domain.User">
        "id" resultType="java.lang.Integer" order="AFTER">
            select LAST_INSERT_ID()
        
        insert into user(username, birthday, sex, address) values(#{username}, #{birthday}, #{sex}, #{address})
    
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 映射文件的配置



    
    <select id="getUserByQueryVo" parameterType="queryvo" resultType="user">
        select * from user where id = #{user.id}
    select>
mapper>
1.3 解决数据库表和实体类字段不对应方法
1. 第一种: sql语句利用起别名的方式解决字段不一致问题.




<mapper namespace="Mapper.OrderMapper">
    
    
    
    <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>
    
    <select id="getOrderList" resultMap="order_list_result">
        select * from orders
    select>
mapper>

2.动态生成sql语句

2.1 if(判断), where解决了第一个and出现的问题

<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遍历

    
    <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 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 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查询结果的字段.

<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

<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.一对多关联映射查询


    <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>

你可能感兴趣的:(Mybatis详解)