SSM框架系列学习总结5之Mybatis实现基本CRUD和代理开发模式

首先, 回顾Mybatis的入门使用方法:

  1. 创建Java工程
  2. 导入相关jar包


    jar.png

其中, 需要数据库驱动包, Mybatis核心包, 包括JUnit单元测试所需的jar包 hamcrest-corejunit-4.12
日志格式输出的jar包 log4jcommons-logging

  1. 准备Mybatis的全局配置文件
    具体内容见上一篇整理的博客!
  2. 准备Mybatis的映射文件
    在映射文件中编写sql语句







单元测试程序:


单元测试.png

SqlSession对象的获取和使用:

SqlSessionFactoryBuilder  --->  SqlSessionFactory ---> SqlSession
SqlSessionFactoryBuilder : build(InputStream in) 获取SqlSessionFactory
SqlSessionFactory :    openSession()    获取SqlSession 

SqlSession:
selectOne(String id , Object param);
selectList(String id ,Object param);
insert()
delete()
update()

CRUD

增加

添加用户信息
这里提供了操作的实体类User.java:

public class User {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    // getter and setter, toString() 省略
}
添加.png

    
        
            select last_insert_id()
        

        
        
            
        

        insert into `user` values(#{id}, #{username}, #{birthday}, #{sex}, #{address})
    

单元测试代码:

    @Test
    public void insertUser() throws Exception {
        // 得到全局配置文件的输入流对象
        InputStream in = Resources.getResourceAsStream("mybatis/sqlMapConfig.xml");
        // 得到Session工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);

        // 得到SqlSession
        SqlSession session = factory.openSession();

        // 创建User对象
        User user = new User();
        user.setUsername("小阳");
        user.setBirthday(new Date());
        user.setSex("1");
        user.setAddress("湖北武汉");
        // 调用的是session的insert()方法
        /*
            还传入的参数是一个User对象
            如果是增删改, 一定要记得提交事务

         */
        session.insert("demo.insertUser", user);
        System.out.println(user);
        session.commit();

        // 关闭session
        session.close();
    }
查询

分多种查询

    

    
    

    
    

这里的单元测试略, 和上面类似.

映射文件:

    
    
        update `user` set username = #{username}, birthday=#{birthday}, sex=#{sex}, address=#{address} where id=#{id}
    

删除

相关映射文件:

    
    
        delete from user where id = #{abc}
    

注意事项:

// 如果查询结果集中有多条记录, 那么使用selectList(String id, Object param)
    /*
        如果这时使用selectOne, 那么这时会抛出
        org.apache.ibatis.exceptions.TooManyResultsException:
        Expected one result (or null) to be returned by selectOne(), but found: 3
        异常
     */
映射文件SQL语句书写小结

parameterType: 输入参数类型, 一定是类型的全名, 或者是别名(int)
resultType: 输出参数类型
#{}: 占位符, 如果是简单类型, 那么里面可以随便写
${}: 是连接符, 如果是简单类型, 那么里面只能是value
如果parameterType是自定义类的类型, 那么#{}, ${}里面都要写该类型的属性名

Mybatis开发Dao层

SqlSession对象: 该对象是线程不安全的, 所以不能定义为成员变量, 只能定义局部变量.
SqlSessionFactory: 该对象在项目中只需要一个, 那么该变量可以定义为成员变量

Dao 接口


接口.png

Dao的实现类:

public class UserDaoImpl implements UserDao {
    private SqlSessionFactory factory;

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

    @Override
    public void addUser(User user) throws Exception {
        SqlSession session = factory.openSession();
        session.insert("demo.insertUser", user);
        session.commit();
        session.close();
    }

    @Override
    public void deleteUser(Integer id) throws Exception {
        SqlSession session = factory.openSession();
        session.delete("demo.deleteById", id);
        session.commit();
        session.close();
    }

    @Override
    public void updateUser(User user) throws Exception {
        SqlSession session = factory.openSession();
        session.update("demo.updateUser", user);
        session.commit();
        session.close();
    }

    @Override
    public User findUserById(Integer id) throws Exception {
        // 获取SqlSession对象
        SqlSession session = factory.openSession();
        User user = session.selectOne("demo.findUserById", id);
        return user;
    }

    @Override
    public List findAllUser() throws Exception {
        SqlSession session = factory.openSession();
        List userList = session.selectList("demo.findAllUser");
        return userList;
    }
}

测试类:

public class UserDaoImplTest {

    private SqlSessionFactory factory;

    // 用来获取工厂
    @Before
    public void getFactory() throws Exception {
        this.factory = new SqlSessionFactoryBuilder().
                build(Resources.getResourceAsStream("mybatis/sqlMapConfig.xml"));
    }

    @Test
    public void testFindUser() throws Exception {
        // 获取UserDao对象
        UserDao userDao = new UserDaoImpl(factory);
        User user = userDao.findUserById(28);
        System.out.println(user);
    }

    @Test
    public void testFindAllUser() throws Exception {
        // 获取UserDao对象
        UserDao userDao = new UserDaoImpl(factory);
        List userList = userDao.findAllUser();
        System.out.println(userList);
    }

    @Test
    public void testAddUser() throws Exception {
        // 获取UserDao对象
        UserDao userDao = new UserDaoImpl(factory);
        User user = new User();
        user.setUsername("小花");
        user.setSex("2");
        user.setBirthday(new Date());
        user.setAddress("武汉");
        userDao.addUser(user);

        System.out.println(user);
    }

    @Test
    public void deleteUser() throws Exception {
        // 获取UserDao对象
        UserDao userDao = new UserDaoImpl(factory);
        userDao.deleteUser(29);

    }

    @Test
    public void updateUser() throws Exception {
        // 获取UserDao对象
        UserDao userDao = new UserDaoImpl(factory);
        User user = new User();
        user.setId(28);
        user.setUsername("小阳");
        user.setSex("2");
        user.setBirthday(new Date());
        user.setAddress("武汉");
        userDao.updateUser(user);

        System.out.println(user);
    }
}

Mapper代理模式开发DAO

上面的dao传统开发模式有两个不太好的地方:

  1. 我们需要在每个dao方法中去获取SqlSession对象, 并且调用SqlSession中的方法, 在每个方法中都是差不多的.
  2. 在每次调用SqlSession方法的时候, 传入的第一个参数都是硬编码, 写死了, 不好!!!

由此, 我们引入Mapper代理模式开发dao层
因为在每个dao的实现类的方法中, 存在大量的模板代码, 那么这些代码, 可以通过一个代理对象来调用. 但是这个代理对象根据dao的接口来生成, 所以在Mapper代理开发中, 我只需要编写dao的接口, 不需要编写其实现类.

1. 准备映射文件

如果采用的mapper代理开发模式, 那么映射文件的命名空间必须是
Mapper接口的全路径


全路径.png
2. 编写接口中的方法

三个特点:
1. Mapper接口中的方法名必须和映射文件中的sql语句的id一致
2. Mapper接口中的方法的返回值类型必须和resultType一致, 如果返回的
结果有多条记录, 那么返回值是List, 但是元素类型和resultType一致
3. Mapper接口中的方法参数必须和映射文件中parameterType一致
见代码:

/**
 * mapper开发的接口
 * Created by menglanyingfei
 * on 2018/1/20.
 */
public interface UserMapper {
    List findUserByName(String name);
}





    
    

  


测试代码:

public class MapperTest {
    private SqlSessionFactory factory;

    @Before
    public void getFactory() throws Exception {
        this.factory = new SqlSessionFactoryBuilder().
                build(Resources.getResourceAsStream("mybatis/sqlMapConfig.xml"));
    }

    @Test
    public void testFindUserByName() {
        // 获取SqlSession
        SqlSession session = factory.openSession();
        // 通过SqlSession对象得到Mapper接口的一个代理对象
        // 需要传递的参数是Mapper接口的类型
        UserMapper userMapper = session.getMapper(UserMapper.class);
        // 通过代理对象调用UserMapper中的方法
        List userList = userMapper.findUserByName("小");
        System.out.println(userList);
        // 红色标识!
        System.err.println(userMapper);
        // org.apache.ibatis.binding.MapperProxy@289d1c02
        // 关闭资源
        session.close();
    }

Mybatis全局配置文件的一些配置信息

properties(属性)
settings(全局配置参数)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境集合属性对象)
-- environment(环境子属性对象)
---- transactionManager(事务管理)
---- dataSource(数据源)
mappers(映射器)

注意:上面几项配置, 必须按照顺序进行配置

settings(全局配置参数)

该配置中可以配置全局参数, 比如二级缓存, 延迟加载和日志信息的配置
配置信息参考: mybatis-settings.xlsx(包含在下面的代码文件夹中)

    
    
        
    
properties: 一般用来配置数据库的连接信息

在properties标签体, 还可以通过property标签来设置属性, 但是此时的加载顺序是先加载的是property标签中的属性, 然后再加载resource指定的外部属性文件中的属性.

    
    
        
    
typeAliases(类型别名, 重要)

Mybatis默认支持的别名


别名.png

自定义别名:

  1. 配置单个别名:


    image.png
  2. 批量配置别名: mybatis扫描某一个包, 对包下的所有类都创建别名

    image.png


    
        
        
        
    

typeHandlers(类型处理器)
一般不需要配置


image.png

补充(但使用较少!):


    
        
            
            
                
                
                
                
            
        
    
mappers(映射器)

用来在全局配置文件中加载映射文件
加载单个映射文件


        
        

        
        

        
        

        
        
    

完!
完整代码地址见:
https://github.com/menglanyingfei/SSMLearning/tree/master/mybatis_day02

你可能感兴趣的:(SSM框架系列学习总结5之Mybatis实现基本CRUD和代理开发模式)