SSM————Mybatis(1)

一、基本概念:

  Mybatis是apache的一个开源项目iBtis,2010年这个项目由apache software foundation迁移到google code,并且改名MyBatis,2013年11月迁移到GitHub。

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

  Mybatis通过xml或注解的方式将要执行的各种statement(statement、prepareStatement、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后Mybatis框架执行sql并将结果映射成java对象返回。

与jdbc相比较:

  jdbc出现以下缺点:

1、 数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。如果使用数据库连接池可解决此问题。

2、 Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变java代码。

3、 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。

对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。

二、Mybatis架构:

注:sqlSession中包含Executor,Executor中包含MappedStatement

 

1、 mybatis配置

SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

2、 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

3、 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

4、 mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

5、 Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

6、 Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

7、 Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

三、Mybatis入门程序:

  1、mybatis的下载:

mybaits的代码由github.com管理

下载地址:https://github.com/mybatis/mybatis-3/releases

课前资料提供的mybatis如下:

其中:mybatis-3.2.7.jar mybatis的核心包

   lib文件夹 mybatis的依赖包所在

   mybatis-3.2.7.pdf mybatis使用手册

   2、业务需求:

  使用MyBatis实现以下功能:

  根据用户id查询一个用户

  根据用户名称模糊查询用户列表

  添加用户

  更新用户

  删除用户

   3、环境搭建:

    (1)创建java工程    

        如下图使用之前创建的mybatis-first工程

    

    (2)加入jar包

       加入mybatis核心包、依赖包、数据驱动包。

       mybatis核心包

    

       mybatis依赖包

     

      数据库驱动包

     

    (3)加入配置文件

      如下图创建资源文件夹config,加入log4j.propertiesSqlMapConfig.xml配置文件

    

    

       【1】在config下创建log4j.properties如下:(保存运行日志)

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%

      mybatis默认使用log4j作为输出日志信息。

      【2】在config下创建SqlMapConfig.xml如下:(连接各个文件主要是工厂和sql的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>
	<!-- 和spring整合后 environments配置将废除 -->
	<environments default="development">
		<environment id="development">
			<!-- 使用jdbc事务管理 -->
			<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="123" />
			</dataSource>
		</environment>
	</environments>
</configuration>                                 

        SqlMapConfig.xml是mybatis核心配置文件,配置文件内容为数据源、事务管理。

      【3】效果如下:

    

    4、创建pojo(数据封装和JavaBean类似)

       pojo类作为mybatis进行sql映射使用,po类通常与数据库表对应,

       数据库user表如下图:

     

     User.java如下:

Public class User {
	private int id;
	private String username;// 用户姓名
	private String sex;// 性别
	private Date birthday;// 生日
	private String address;// 地址


get/set……

    5、sql映射文件(主要是书写sql语句)

       在config下的sqlmap目录下创建sql映射文件User.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">
<!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 -->

<mapper namespace="test">
<!-- 通过id查询一个用户 -->
<select id="findUserById" parameterType="Integer" resultType="com.itheima.mybatis.pojo.User">
select * from user where id = #{v}
</select>
</mapper>

 占位符:#{任意取名}  select * from user where id = ?   占位符  例如:? == ‘王五’

        ${只能用value}  select * from user where username like  字符串拼接  

  例子:

常用(防注入):

 

    6、加载映射文件(让它找到sql语句)

       mybatis框架需要加载Mapper.xml映射文件

       将users.xml添加在SqlMapConfig.xml,如下:

    

    前面这几步是通用的步骤,其他根据需求编写代码。

 

四、增删改查

五、DAO开发

  使用MyBatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper动态代理开发方法。

  1、需求

    使用MyBatis开发DAO实现以下的功能:

    根据用户id查询一个用户信息

    根据用户名称模糊查询用户信息列表

    添加用户信息

  2、SqlSession的使用范围

    SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。

    SqlSession通过SqlSessionFactory创建。

    SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。

  (1)SqlSessionFactoryBuilder

            SqlSessionFactoryBuilder用于创建SqlSessionFacotySqlSessionFacoty一旦创建完成就不需要       SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory创建的。所以可以将                                         SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。

  (2)SqlSessionFactory

      SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的              最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。

  (3)SqlSession

      SqlSession是一个面向用户的接口,sqlSession中定义了数据库操作方法。每个线程都应该有它自己                  的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方                法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。

    打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行                  关闭。如下:

SqlSession session = sqlSessionFactory.openSession();
try {
     // do work
} finally {
    session.close();
}

 

  3、原始DAO开发方式   

    原始Dao开发方法需要程序员编写Dao接口和Dao实现类。

    (1)映射文件

      编写映射文件如下:(也可以使用入门程序完成映射文件)

<?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,还有一个很重要的作用,后面会讲 -->
<mapper namespace="test">

    <!-- 根据id查询用户 -->
    <select id="queryUserById" parameterType="int"
        resultType="cn.itcast.mybatis.pojo.User">
        select * from user where id = #{id}
    </select>

    <!-- 根据username模糊查询用户 -->
    <select id="queryUserByUsername" parameterType="string"
        resultType="cn.itcast.mybatis.pojo.User">
        select * from user where username like '%${value}%'
    </select>

    <!-- 保存用户 -->
    <insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User">
        <selectKey keyProperty="id" keyColumn="id" order="AFTER"
            resultType="int">
            SELECT LAST_INSERT_ID()
        </selectKey>
        insert into user(username,birthday,sex,address)
        values(#{username},#{birthday},#{sex},#{address})
    </insert>

</mapper>

 

    (2)DAO接口

 

      先进行DAO的接口开发,编码如下:

public interface UserDao {
    /**
     * 根据id查询用户
     * 
     * @param id
     * @return
     */
    User queryUserById(int id);

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

    /**
     * 保存用户
     * 
     * @param user
     */
    void saveUser(User user);
}

 

 

    (3)DAO实现类 

      编写的Dao实现类如下

public class UserDaoImpl implements UserDao {
    private SqlSessionFactory sqlSessionFactory;

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

    @Override
    public User queryUserById(int id) {
        // 创建SqlSession
        SqlSession sqlSession = this.sqlSessionFactory.openSession();
        // 执行查询逻辑
        User user = sqlSession.selectOne("queryUserById", id);
        // 释放资源
        sqlSession.close();

        return user;
    }

    @Override
    public List<User> queryUserByUsername(String username) {
        // 创建SqlSession
        SqlSession sqlSession = this.sqlSessionFactory.openSession();

        // 执行查询逻辑
        List<User> list = sqlSession.selectList("queryUserByUsername", username);
        // 释放资源
        sqlSession.close();
        return list;
    }

    @Override
    public void saveUser(User user) {
        // 创建SqlSession
        SqlSession sqlSession = this.sqlSessionFactory.openSession();

        // 执行保存逻辑
        sqlSession.insert("saveUser", user);
        // 提交事务
        sqlSession.commit();
        // 释放资源
        sqlSession.close();
    }
}

 

 

 

    (4)DAO测试

      创建一个JUnit的测试类,对UserDao进行测试,测试代码如下:

public class UserDaoTest {
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws Exception {
        // 创建SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 加载SqlMapConfig.xml配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 创建SqlsessionFactory
        this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
    }

    @Test
    public void testQueryUserById() {
        // 创建DAO
        UserDao userDao = new UserDaoImpl(this.sqlSessionFactory);
        // 执行查询
        User user = userDao.queryUserById(1);
        System.out.println(user);
    }

    @Test
    public void testQueryUserByUsername() {
        // 创建DAO

        UserDao userDao = new UserDaoImpl(this.sqlSessionFactory);
        // 执行查询
        List<User> list = userDao.queryUserByUsername("张");
        for (User user : list) {
            System.out.println(user);
        }
    }

    @Test
    public void testSaveUser() {
        // 创建DAO
        UserDao userDao = new UserDaoImpl(this.sqlSessionFactory);

        // 创建保存对象
        User user = new User();
        user.setUsername("刘备");
        user.setBirthday(new Date());
        user.setSex("1");
        user.setAddress("蜀国");
        // 执行保存
        userDao.saveUser(user);

        System.out.println(user);
    }
}

 

  4、Mapper动态代理开发

    (1)开发规范

      Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口               定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

      Mapper接口开发需要遵循以下规范:

      1、 接口方法名 == User.xml中的id名

      2、返回值类型与Mapper.xml文件中返回值类型要一致

      3、 方法入参类型与Mapper.xml中入参的类型要一致

      4、 命名空间绑定此接口

    (2)Mapper.xml(映射文件)

        定义mapper映射文件UserMapper.xml

        将UserMapper.xml放在config下mapper目录下,效果如下:

          

        UserMapper.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">
<!-- namespace:命名空间,用于隔离sql -->
<!-- 还有一个很重要的作用,使用动态代理开发DAO,1. namespace必须和Mapper接口类路径一致 -->
<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">
    <!-- 根据用户id查询用户 -->
    <!-- 2. id必须和Mapper接口方法名一致 -->
    <!-- 3. parameterType必须和接口方法参数类型一致 -->
    <!-- 4. resultType必须和接口方法返回值类型一致 -->
    <select id="queryUserById" parameterType="int"
        resultType="cn.itcast.mybatis.pojo.User">
        select * from user where id = #{id}
    </select>

    <!-- 根据用户名查询用户 -->
    <select id="queryUserByUsername" parameterType="string"
        resultType="cn.itcast.mybatis.pojo.User">
        select * from user where username like '%${value}%'
    </select>

    <!-- 保存用户 -->
    <insert id="saveUser" parameterType="cn.itcast.mybatis.pojo.User">
        <selectKey keyProperty="id" keyColumn="id" order="AFTER"
            resultType="int">
            select last_insert_id()
        </selectKey>
        insert into user(username,birthday,sex,address) values
        (#{username},#{birthday},#{sex},#{address});
    </insert>

</mapper>

 

    (3)UserMapper(接口文件)

      创建UserMapper接口代码如下:

public interface UserMapper {
    /**
     * 根据id查询
     * 
     * @param id
     * @return
     */
    User queryUserById(int id);

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

    /**
     * 保存用户
     * 
     * @param user
     */
    void saveUser(User user);
}

 

    (4)加载UserMapper.xml文件

      修改SqlMapConfig.xml文件,添加以下所示的内容:

    <!-- 加载映射文件 -->
    <mappers>
        <mapper resource="sqlmap/User.xml" />
        <mapper resource="mapper/UserMapper.xml" />
    </mappers>

    (5)测试

      编写的测试方法如下:

public class UserMapperTest {
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws Exception {
        // 创建SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 加载SqlMapConfig.xml配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 创建SqlsessionFactory
        this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
    }

    @Test
    public void testQueryUserById() {
        // 获取sqlSession,和spring整合后由spring管理
        SqlSession sqlSession = this.sqlSessionFactory.openSession();

        // 从sqlSession帮我生成一个实现类(给接口)
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 执行查询方法
        User user = userMapper.queryUserById(1);
        System.out.println(user);

        // 和spring整合后由spring管理
        sqlSession.close();
    }

    @Test
    public void testQueryUserByUsername() {
        // 获取sqlSession,和spring整合后由spring管理
        SqlSession sqlSession = this.sqlSessionFactory.openSession();

        // 从sqlSession中获取Mapper接口的代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 执行查询方法
        List<User> list = userMapper.queryUserByUsername("张");
        for (User user : list) {
            System.out.println(user);
        }

        // 和spring整合后由spring管理
        sqlSession.close();
    }

    @Test
    public void testSaveUser() {
        // 获取sqlSession,和spring整合后由spring管理
        SqlSession sqlSession = this.sqlSessionFactory.openSession();

        // 从sqlSession中获取Mapper接口的代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 创建保存对象
        User user = new User();
        user.setUsername("刘备");
        user.setBirthday(new Date());
        user.setSex("1");
        user.setAddress("蜀国");
        // 执行查询方法
        userMapper.saveUser(user);
        System.out.println(user);


        // 和spring整合后由spring管理
        sqlSession.commit();
        sqlSession.close();
    }
}

   5、小结

      selectOne和selectList

        动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的            返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。

     

      namespace

     mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现               类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。

 

六、关于SqlMapConfig的一些知识点

  1、配置内容

    SqlMapConfigl.xml中配置的内容和顺序如下:

    properties(属性)

    settings(全局配置参数)

    typeAliases(类型别名)

    typeHandlers(类型处理器)

    objectFactory(对象工厂)

    plugins(插件)

    environments(环境集合属性对象)

    environment(环境子属性对象)

    transactionManager(事务管理)

    dataSource(数据源)

    mappers(映射器)

  2、properties(属性)

    SqlMapConfig.xml可以引用java属性文件中的配置信息如下:

    在config下定义db.properties文件,如下所示:

    

    db.properties配置文件内容如下:

1 jdbc.driver=com.mysql.jdbc.Driver
2 jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
3 jdbc.username=root
4 jdbc.password=root

    SqlMapConfig.xml引用如下:

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE configuration
 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <configuration>
 6     <!-- 是用resource属性加载外部配置文件 -->
 7     <properties resource="db.properties">
 8         <!-- 在properties内部用property定义属性 -->
 9         <!-- 如果外部配置文件有该属性,则内部定义属性被外部属性覆盖 -->
10         <property name="jdbc.username" value="root123" />
11         <property name="jdbc.password" value="root123" />
12     </properties>
13 
14     <!-- 和spring整合后 environments配置将废除 -->
15     <environments default="development">
16         <environment id="development">
17             <!-- 使用jdbc事务管理 -->
18             <transactionManager type="JDBC" />
19             <!-- 数据库连接池 -->
20             <dataSource type="POOLED">
21                 <property name="driver" value="${jdbc.driver}" />
22                 <property name="url" value="${jdbc.url}" />
23                 <property name="username" value="${jdbc.username}" />
24                 <property name="password" value="${jdbc.password}" />
25             </dataSource>
26         </environment>
27     </environments>
28 
29     <!-- 加载映射文件 -->
30     <mappers>
31         <mapper resource="sqlmap/User.xml" />
32         <mapper resource="mapper/UserMapper.xml" />
33     </mappers>
34 </configuration>

    注意: MyBatis 将按照下面的顺序来加载属性:

    在 properties 元素体内定义的属性首先被读取。

    然后会读取properties 元素中resource或 url 加载的属性,它会覆盖已读取的同名属性。

  3、typeAliases(类型别名)

                (1)mybatis支持别名:

  

  

    (2)自定义别名

    在SqlMapConfig.xml中配置如下:

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE configuration
 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4 "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <configuration>
 6     <!-- 是用resource属性加载外部配置文件 -->
 7     <properties resource="db.properties">
 8         <!-- 在properties内部用property定义属性 -->
 9         <property name="jdbc.username" value="root123" />
10         <property name="jdbc.password" value="root123" />
11     </properties>
12 
13     <typeAliases>
14         <!-- 单个别名定义 -->
15         <typeAlias alias="user" type="cn.itcast.mybatis.pojo.User" />
16         <!-- 批量别名定义,扫描整个包下的类,别名为类名(大小写不敏感) -->
17         <package name="cn.itcast.mybatis.pojo" />
18         <package name="其它包" />
19     </typeAliases>
20 
21     <!-- 和spring整合后 environments配置将废除 -->
22     <environments default="development">
23         <environment id="development">
24             <!-- 使用jdbc事务管理 -->
25             <transactionManager type="JDBC" />
26             <!-- 数据库连接池 -->
27             <dataSource type="POOLED">
28                 <property name="driver" value="${jdbc.driver}" />
29                 <property name="url" value="${jdbc.url}" />
30                 <property name="username" value="${jdbc.username}" />
31                 <property name="password" value="${jdbc.password}" />
32             </dataSource>
33         </environment>
34     </environments>
35 
36     <!-- 加载映射文件 -->
37     <mappers>
38         <mapper resource="sqlmap/User.xml" />
39         <mapper resource="mapper/UserMapper.xml" />
40     </mappers>
41 </configuration>

 

    在mapper.xml配置文件中,就可以使用设置的别名了

    别名大小写不敏感

  4、mappers(映射器)

    Mapper配置的几种方法:

     (1)<mapper resource=" "/>

      使用相对于类路径的资源(常用)

      如:<mapper resource="sqlmap/User.xml" />

     (2)<mapper class=" "/>

      使用mapper接口类路径

      如:<mapper class="cn.itcast.mybatis.mapper.UserMapper"/>

      注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

     (3)<package name=" "/>

      注册指定包下的所有mapper接口

      如:<package name="cn.itcast.mybatis.mapper"/>

      注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

 

 

七、整合(Spring)后开发常用

class  容器中已经加载的工厂路径

name  定义扫描的单元

value  定义扫描该包或者该包下的所有子包中的类

 

posted @ 2019-02-21 11:15  小菜鸡哒  阅读(113)  评论(0)    收藏  举报