MyBatis笔记(一)

一、MyBatis是什么?

MyBatis是一个优秀的基于Java的持久层框架,它内部封装了JDBC,使开发者只需要关注SQL语句本身,而不需要花费精力去处理加载驱动、创建连接、创建Statement等繁杂的过程。

二、JDBC有哪些缺点?

JDBC程序示例:

    public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            //加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            //通过驱动管理类获取数据库链接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
            //定义 sql 语句 ?表示占位符
            String sql = "select * from user where username = ?";
            //获取预处理 statement
            preparedStatement = connection.prepareStatement(sql);
            //设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的参数值
            preparedStatement.setString(1, "王五");
            //向数据库发出 sql 执行查询,查询出结果集
            resultSet = preparedStatement.executeQuery();
            //遍历查询结果集
            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) {
                    e.printStackTrace();
                }
            }
            if(preparedStatement!=null){
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

JDBC存在的问题:

  1. 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
  2. SQL语句在代码中硬编码,造成代码不易维护,实际应用SQL变化的可能较大,SQL变动需要改变Java代码。
  3. 使用PreparedStatement向占有位符号传参数存在硬编码,因为SQL语句的where条件不一定,可能多也可能少,修改SQL还要修改代码,系统不易维护。
  4. 对结果集解析存在硬编码(查询列名),SQL变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。

三、MyBatis环境搭建步骤

  1. 创建Maven工程
GroupId: com.itheima
ArtifactId: mybatis01
  1. 导入依赖坐标pom.xml
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>
    </dependencies>
  1. 编写实体类com/itheima/domain/User.java
package com.itheima.domain;

import lombok.Data;
import java.io.Serializable;
import java.util.Date;

@Data
public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
}
  1. 编写持久层接口com/itheima/dao/UserDao.java
package com.itheima.dao;

import com.itheima.domain.QueryVo;
import com.itheima.domain.User;
import java.util.List;

public interface UserDao {

    /**
     * 查询所有用户
     * @return
     */
    List<User> findAll();

    /**
     * 根据id查询用户
     * @param id
     * @return
     */
    User findById(Integer id);

    /**
     * 保存用户
     * @param user
     * @return
     */
    int saveUser(User user);

    /**
     * 更新用户
     * @param user
     * @return
     */
    int updateUser(User user);

    /**
     * 删除用户
     * @param id
     * @return
     */
    int deleteUser(Integer id);

    /**
     * 根据用户名模糊查询
     * @param username
     * @return
     */
    List<User> findByName(String username);

    /**
     * 查询用户数量
     * @return
     */
    Integer findCount();

    /**
     * 根据QueryVo中的条件查询用户
     * @param vo
     * @return
     */
    List<User> findByVo(QueryVo vo);
}

  1. 编写MyBatis配置文件SqlMapConfig.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>
    <typeAliases>
        <package name="com.itheima.domain"/>
    </typeAliases>

    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ee50"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <package name="com.itheima.dao"/>
    </mappers>

</configuration>
  1. 编写映射配置文件com/itheima/dao/UserDao.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.itheima.dao.UserDao">
    <select id="findAll" resultType="User">
        select * from user
    </select>
    <select id="findById" resultType="User" parameterType="int">
        select * from user where id = #{id}
    </select>
    <insert id="saveUser" parameterType="User">
        <selectKey keyColumn="id" keyProperty="id" resultType="int">
            select last_insert_id();
        </selectKey>
        insert into user(username, birthday, sex, address)
            values(#{username}, #{birthday}, #{sex}, #{address})
    </insert>
    <update id="updateUser" parameterType="User">
        update user set username=#{username}, birthday=#{birthday}, sex=#{sex},
            address=#{address} where id=#{id}
    </update>
    <delete id="deleteUser" parameterType="int">
        delete from user where id=#{id}
    </delete>

    <select id="findByName" parameterType="string" resultType="User">
        select * from user where username like #{username}
    </select>
    <select id="findCount" resultType="int">
        select count(*) from user
    </select>

    <select id="findByVo" resultType="User" parameterType="QueryVo">
        select * from user where username like #{user.username}
    </select>
</mapper>
  1. 编写测试类com/itheima/test/MyBatisTests.java
package com.itheima.test;

import com.itheima.dao.UserDao;
import com.itheima.domain.QueryVo;
import com.itheima.domain.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class MyBatisTests {

    private InputStream in ;
    private SqlSessionFactory factory;
    private SqlSession session;
    private UserDao userDao;

    // 一些共有操作
    @Before
    public void init() throws IOException{
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        factory = builder.build(in);
        session = factory.openSession();
        userDao = session.getMapper(UserDao.class);
    }

    @After
    public void destroy() throws Exception {
        session.commit();
        session.close();
        in.close();
    }


    @Test
    public void testSelectAll() {
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println(user);
        }
    }

    @Test
    public void testSelectById() {
        User user = userDao.findById(1);
        System.out.println(user);
    }

    @Test
    public void testSaveUser() {
        User user = new User();
        user.setUsername("xxx");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("china");
        int i = userDao.saveUser(user);
        System.out.println(i);
        System.out.println(user.getId());
    }

    @Test
    public void testUpdateUser() {
        User user = userDao.findById(2);
        user.setAddress("JiangSu");
        int i = userDao.updateUser(user);
        System.out.println(i);
    }

    @Test
    public void testDeleteUser() {
        int i = userDao.deleteUser(4);
        System.out.println(i);
    }

    @Test
    public void testFindByName() {
        List<User> userList = userDao.findByName("%g%");
        for (User user : userList) {
            System.out.println(user);
        }
    }

    @Test
    public void testFindCount() {
        int i = userDao.findCount();
        System.out.println(i);
    }

    @Test
    public void testFindByVo() {
        QueryVo vo = new QueryVo();
        User user = new User();
        user.setUsername("%w%");
        vo.setUser(user);
        List<User> userList = userDao.findByVo(vo);
        for (User resUser : userList) {
            System.out.println(resUser);
        }
    }
}

四、补充说明

  1. UserDao.javaUserDao.xml两个文件分别在java包和resources包下,其路径必须保持一致且名字相同。
  2. UserDao.xml中的mapper的几个属性:namespace为对应的持久层接口UserDao.java的全限定类名,id为UserDao.java中相应的方法名,<selectkey>用于新增User后自动返回id属性值。
  3. UserDao.xml中的resultType和parameterType:若是基本类型和String类型,可以直接写类名;若是实体类,如User,则需要写全限定类名。可以在SqlMapConfig.xml中注册别名:
<typeAliases>
    <package name="com.itheima.domain"/>
</typeAliases>

注册过后,该包下的实体类都可以用别名,及类名,首字母不区分大小写。
4. 需要在SqlMapConfig.xml中配置映射器(mappers),一种比较方便的方法是设置整个包:

<mappers>
    <package name="com.itheima.dao"/>
</mappers>

要求mapper接口和mapper映射文件包路径一致且名字相同。
5. MyBatis也可以不编写mapper映射文件,可以将SQL语句写在mapper接口中相应方法的上面,例如:

/**
* 查询所有用户
* @return
*/
@Select("select * from user")
List<User> findAll();

这种方式少些一个XML文件,看着比较简洁。但是一般工程不采用该方式,个人猜想是因为SQL和Java方法之间产生了耦合,修改维护不方便。

posted @ 2021-07-28 20:15  阿松0919  阅读(41)  评论(0)    收藏  举报