MyBatis的介绍和入门

一.Mybatis介绍

概念

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL
本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

背景

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation
迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

二.mybatis的入门案例

需求1: 根据id查询一个用户

掌握的内容: mybatis如何来使用.

1.准备环境

  1. mysql的jar ; mybatis的jar junit的jar , lombok.jar,日志
<dependencies>
	<!-- mysql的jar -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
   <!--mybatis的jar -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
  <!-- junit的jar -->  
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
     <!-- lombok的jar -->  
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
        </dependency>
  <!-- 日志的jar -->  
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.6</version>
        </dependency>
    </dependencies>
  • 创建一个SqlSessionFactoryBuilder 对象 (工厂构建对象) 方法build (InputStream)
  • Resources类,静态方法getResourcesAsStream(“加载核心配置文件SqlMapConfig.xml”) 得到一个InputStream流对象
  • 使用build方法创建一个SqlSessionFacotory ,得到一个会话工厂对象
  • 使用工厂对象调用openSession()方法获取一个SqlSession对象
  • 使用SqlSession对象的查询方法 selectOne(“namespace的id”,实际传递的id值) 得到用户对象
  • 关闭资源
  1. 编写核心配置文件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="development">
        <!-- 环境配置-->
        <environment id="development">
            <!--mybatis的事务管理使用JDBC -->
            <transactionManager type="JDBC"/>
            <!---数据源-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis01"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 加载映射文件-->
    <mappers>
        <!-- 引入指定的映射文件-->
        <mapper resource="UserMapper.xml"></mapper>
    </mappers>

  1. 编写映射文件 UserMapper.xml (编写SQL语句 )
<?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名称空间   作用区分不同模块下的的sql语句
-->

<mapper namespace="user">
    <!-- 需求:根据id查询一个用户的信息
            属性
            id =该条sql语句的唯一标志 ,一会后台需要使用id值,来执行SQL,必须存在
            parameterType 传入过来的参数类型  写的是类的全完全路径名
   --> 
    <select id="findUserById" parameterType="java.lang.Integer" resultType="com.sen.pojo.User">
      <!--
      #{}  来传递参数,是一个占位符
      如果是基本数据类型或者字符串String 值可以写任意值 #{任意值}
      如果穿的是参数类型是pojo类型,值要传递pojo的属性值
      -->
        <!-- 根据id 查询sql语句-->
      select  * from user  where id = #{id}
    </select>
    
    <!--
            2.根据name模糊查询
              如果返回值类型是List<User> resultType中 集合的泛型
-->
    <select id="findUserByName" parameterType="java.lang.String" resultType="com.sen.pojo.User">
        select  * from user where username like #{name}
    </select>
    <!--
           3.根据name模糊查询(版本2)
               如果返回值类型是List<User> resultType中 集合的泛型
               ${} 字符串拼接方式传递参数
                接受的参数类型如果是基本数据类型  只能写 value
       -->
    <select id="findUserByName2" parameterType="java.lang.String" resultType="com.sen.pojo.User">
        select  * from user where username like '%${value}%'
    </select>

    <!--
         4.添加一个用户
            直接传递一个User对象   (自动完成映射)
     -->
    <insert id="addUser" parameterType="com.sen.pojo.User">
    <!--parameterType:如果参数类型是一个POJO对象,#{POJo的属性值}
     private  int id;
    private  String username;
    private Date birthday;
    private String sex;
    private  String address;
     -->
        insert into user values(null,#{username},#{birthday},#{sex},#{address})
    </insert>
</mapper>
  1. 在测试类中进行测试 Demo1_Mybatis
@Test
    public void test01() throws IOException {
        //1.创建SqlSessionFactoryBuilder 对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //2.Resources调用getResourceAsStream(核心配置文件)  返回一个流
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //3.SqlSessionFactoryBuilder 对象有一个build方法(流) ,返回一个SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
        //4.通过SqlSessionFactory 的openSession方法获取到一个SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();//参数:true 自动提交事务/false 手动提交事务(默认值)
//这里注意    查询一般默认不写(false)

        //5.通过SqlSession调用一个selectOne("namespace的id.sql语句的id值", 实际查询的用户的id值) 返回一个user对象
        User user = sqlSession.selectOne("user.findUserById",10);
        //6.打印对象
        System.out.println(user);
        //7.关闭资源
        inputStream.close();
        sqlSession.close();
    }

三.使用MyBaits来完成Dao层的编写 (原始方式)

UserDao–UserDaoImpl

public interface UserDao {

    //根据id查询
    public User findUserById(int id);

    //根据name模糊查询

    public List<User> findUserByName(String name);

    //添加用户
    public void addUser(User user);

}
/**
 * 添加用户:
 * sqlSession.调用增删改查的方法 --- SqlSessionFactory
 */
public class UserDaoImpl implements UserDao {

    private SqlSessionFactory  sqlSessionFactory;

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

    //根据id查询user
    public User findUserById(int id) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("user.findUserById", id);
        return user;
    }

    //根据name模糊查询user
    public List<User> findUserByName(String name) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> list = sqlSession.selectList("user.findUserByName", name);
        return list;
    }

    //添加用户
    public void addUser(User user) {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        sqlSession.insert("user.addUser",user);
    }
}

测试类

//测试原始的Dao中的方法
public class UserDaoTest {

   private  UserDao dao = null;

    @Before
    public void init() throws IOException {
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory factory = builder.build(inputStream);
        //创建UserDao对象
        dao = new UserDaoImpl(factory);
    }

    @Test
    public void findUserByIdTest() throws IOException {
        User user = dao.findUserById(1);
        System.out.println(user);
    }

    @Test
    public void findUserByNameTest() {
        List<User> list = dao.findUserByName("张");
        System.out.println(list);
    }

    @Test
    public void addUserTest() {
        User user  = new User("柳岩",new Date(), "2","北京回龙观");
        dao.addUser(user);
    }
}

三.mybatis的动态代理方式开发dao (重点)

动态代理的注意事项

  • 第一个特点是编写之后接口没有实现类,dao改名mapper (包名修改mapper 接口也要修改UserMapper)

  • UserMapper.xml映射文件中有四个规则

    1. namespace的名称为接口的完全路径名
    2. sql语句的id值必须和接口中方法的名称一致
    3. SQL语句的参数类型与接口方法中的参数类型一致
    4. SQL语句的返回值类型与接口方法的返回值类型一致 (集合写的是泛型)

图解:
在这里插入图片描述在这里插入图片描述

  • 之前的方法有改动
    • sqlSession会话对象的方法更变为 getMapper(接口的字节码对象), 该方法返回的是接口的子类代理对象.

UserMapper接口–接口的测试类


public interface UserMapper {

        public User findUserById(int id);

        public List<User> findByName(String name);

        public void insertUser(User user);
}
/**
 * 之前获取工厂对象方式和以前一致,从sqlSession调用方法开始不一致
 *
 */
public class UserMapperTest {

    private SqlSessionFactory factory = null;
    @Before
    public void init() throws IOException {
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = builder.build(inputStream);
    }

    @Test
    public void findUserById() {
        SqlSession sqlSession = factory.openSession();
        //通过sqlSession的getMapper方法获取到接口的子类代理对象 : 动态代理模式
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.findUserById(1);
        System.out.println(user);
    }

    @Test
    public void findByName() {
        SqlSession sqlSession = factory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> list = mapper.findByName("张");
        for (User user : list) {
            System.out.println(user);
        }
    }

    @Test
    public void insertUser() {
        SqlSession sqlSession = factory.openSession(true);
        User user = new User("柳传志",new Date(), "1","昌平");
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.insertUser(user);
    }
}

个人注意事项:

  • java.lang.Integer

  • SqlMapConfig

    • <!- - 引入指定的映射文件-- >
      < mapper resource=“UserMapper.xml”>< /mapper>
    • < property name=“url” value=“jdbc:mysql:///mybatis01”/>
  • mybatis的动态代理方式开发dao

    • UserMapper.xml
      • < mapper namespace=“com.sen.mapper.UserMapper”>
      • ${} 字符串拼接方式传递参数
        接受的参数类型如果是基本数据类型 只能写 value
      • 如果返回值类型是List resultType中 集合的泛型
      • resultType=“com.sen.pojo.User”
      • 模糊查询
        - select * from user where username like ‘%${value}%’

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值