【Java中级】30.0 SSM之Mybatis框架(一)——入门、增删查改、架构和动态代理Dao包装

1.0 Java后台项目框架分为web层、业务层、Dao层(持久层)。

三者采用什么架构没有非常必然的联系。所以就有了SSM和SSH等不同的组合方式。

2.0 常见的持久层框架

DBUtils , Hibernate,Mybatis。

3.0 为什么学Mybatis?
    1. 目前最主流的持久层框架为hibernate与mybatis,而且国内目前情况使用Mybatis的公司比hibernate要多。
    1. Hibernate学习门槛不低,要精通门槛更高。门槛高在怎么设计O/R映射,在性能和对象模型之间如何权衡取得平衡,以及怎样用好Hibernate缓存与数据加载策略方面需要你的经验和能力都很强才行。国内目前前的情况精通hibernate技术大牛非常少。
    1. sql优化方面,Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。当然了,Hibernate也可以自己写SQL来指定需要查询的字段,但这样就破坏了Hibernate开发的简洁性。说得更深入一些,如果有个查询要关联多张表,比如5张表,10张表时,而且,我们要取的字段只是其中几张表的部分字段。这时用hibernate时就会显得非常力不从心。就算用hibernate的sqlquery,后续的维护工作也会让人发狂
4.0 2JDBC编程回顾与存在的问题分析
4.1 开发步骤
  • 1.导入数据脚本,在课前资料中有
  • 2.创建工程,导入mysql jar包
  • 3.编码
4.2Jdbc访问数据库的过程:
1.加载数据库驱动
2.创建数据库连接
3.创建statement
4.设置sql语句
5.设置查询参数
6.执行查询,得到ResultSet
7.解析结果集ResultSet
8.释放资源
5.0 Mybatis介绍
  • MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
  • Mybatis是面向sql的持久层框架,他封装了jdbc访问数据库的过程,我们开发,只需专注于sql语句本身的拼装,其它复杂的过程全部可以交给mybatis去完成。
6.0 Mybaits入门
6.1 建立数据库
/*
Navicat MySQL Data Transfer

Source Server         : localhost_3306
Source Server Version : 50521
Source Host           : localhost:3306
Source Database       : mybatis

Target Server Type    : MYSQL
Target Server Version : 50521
File Encoding         : 65001

Date: 2015-04-09 16:03:53
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `orders`
-- ----------------------------
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL COMMENT '下单用户id',
  `number` varchar(32) NOT NULL COMMENT '订单号',
  `createtime` datetime NOT NULL COMMENT '创建订单时间',
  `note` varchar(100) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`),
  KEY `FK_orders_1` (`user_id`),
  CONSTRAINT `FK_order_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of orders
-- ----------------------------
INSERT INTO `order` VALUES ('3', '1', '1000010', '2015-02-04 13:22:35', null);
INSERT INTO `order` VALUES ('4', '1', '1000011', '2015-02-03 13:22:41', null);
INSERT INTO `order` VALUES ('5', '10', '1000012', '2015-02-12 16:13:23', null);

-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `sex` char(1) DEFAULT NULL COMMENT '性别',
  `address` varchar(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', '王五', null, '2', null);
INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '北京市');
INSERT INTO `user` VALUES ('16', '张小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('22', '陈小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('24', '张三丰', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('25', '陈小明', null, '1', '河南郑州');
INSERT INTO `user` VALUES ('26', '王五', null, null, null);

6.2 工程搭建
image.png
1.导入依赖jar包
2.配置SqlMapConfig.xml
3.配置log4j.properties
5.配置sql查询的映射文件
6.加载映射文件
image.png

这里我本地数据库版本是MySQL 8.0.18。
SqlMapConfig.xml




    

    
    
        
        
            
            
            
            
                
                
                    
                
                
            
        
    
    

    

    
    

log4j.properties

log4j.rootLogger=DEBUG, Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

也可以这样配置:

# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE            debug   info   warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n

User.java

package com.edp.mybatis.domain;

/**
 * User的实体类:用户
 * 
 * @author edpeng
 * @DATE 2020年02月18日
 *       CREATE TABLE `user` (
 *       `id` int(11) NOT NULL AUTO_INCREMENT,
 *       `username` varchar(32) NOT NULL COMMENT '用户名称',
 *       `birthday` date DEFAULT NULL COMMENT '生日',
 *       `sex` char(1) DEFAULT NULL COMMENT '性别',
 *       `address` varchar(256) DEFAULT NULL COMMENT '地址',
 *       PRIMARY KEY (`id`)
 *       ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
 * 
 *       添加数据
 *       INSERT INTO `user` VALUES ('1', '王五', null, '2', null);
 *       INSERT INTO `user` VALUES ('10', '张三', '2014-07-10', '1', '北京市');
 *       INSERT INTO `user` VALUES ('16', '张小明', null, '1', '河南郑州');
 *       INSERT INTO `user` VALUES ('22', '陈小明', null, '1', '河南郑州');
 *       INSERT INTO `user` VALUES ('24', '张三丰', null, '1', '河南郑州');
 *       INSERT INTO `user` VALUES ('25', '陈小明', null, '1', '河南郑州');
 *       INSERT INTO `user` VALUES ('26', '王五', null, null, null);
 * 
 */

import java.util.Date;

public class User {

    private Integer id;
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address="
                + address + "]";
    }
}

Order.java

package com.edp.mybatis.domain;

/**
 * Order的实体类:订单
 * 
 * @author edpeng
 * @DATE 2020年02月18日
 *       CREATE TABLE `order` (
 *       `id` int(11) NOT NULL AUTO_INCREMENT,
 *       `user_id` int(11) NOT NULL COMMENT '下单用户id',
 *       `number` varchar(32) NOT NULL COMMENT '订单号',
 *       `createtime` datetime NOT NULL COMMENT '创建订单时间',
 *       `note` varchar(100) DEFAULT NULL COMMENT '备注',
 *       PRIMARY KEY (`id`),
 *       KEY `FK_orders_1` (`user_id`),
 *       CONSTRAINT `FK_order_id` FOREIGN KEY (`user_id`) REFERENCES `user`
 *       (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
 *       ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
 * 
 *       添加数据
 *       INSERT INTO `order` VALUES ('3', '1', '1000010', '2015-02-04 13:22:35', null);
 *       INSERT INTO `order` VALUES ('4', '1', '1000011', '2015-02-03 13:22:41', null);
 *       INSERT INTO `order` VALUES ('5', '10', '1000012', '2015-02-12 16:13:23', null);
 */
import java.util.Date;

public class Order {
    private Integer id;

    private Integer userId;

    private String number;

    private Date createtime;

    private String note;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number == null ? null : number.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note == null ? null : note.trim();
    }

    @Override
    public String toString() {
        return "Order [id=" + id + ", userId=" + userId + ", number=" + number + ", createtime=" + createtime
                + ", note=" + note + "]";
    }
}

User.xml







    
    
    
    
    

环境搭建的注意事项:

  • 第一个:创建IUserDao.xml 和 IUserDao.java时名称是为了和我们之前的知识保持一致。
    在Mybatis中它把持久层的操作接口名称和映射文件也叫做:Mapper
    所以:IUserDao 和 IUserMapper是一样的
  • 第二个:在idea中创建目录的时候,它和包是不一样的
    包在创建时:com.itheima.dao它是三级结构
    目录在创建时:com.itheima.dao是一级目录
  • 第三个:mybatis的映射配置文件位置必须和dao接口的包结构相同
  • 第四个:映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名
  • 第五个:映射配置文件的操作配置(select),id属性的取值必须是dao接口的方法名
  • 当我们遵从了第三,四,五点之后,我们在开发中就无须再写dao的实现类。
6.3 根据用户ID查询用户信息

MybatisDemo1.java测试代码

package com.edp.mybatis.demo;

import java.io.IOException;
import java.io.InputStream;

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.Test;
import com.edp.mybatis.domain.User;

public class MybatisDemo1 {

    @Test
    public void testGetUserById() throws IOException {
        // 创建SqlSessionFactoryBuilder类
        SqlSessionFactoryBuilder ssfBuilder = new SqlSessionFactoryBuilder();
        // Mybatis的工具类Resources
        // 创建核心配置文件的输入流
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 通过输入流创建SqlSessionFactory对象
        SqlSessionFactory ssFactory = ssfBuilder.build(resourceAsStream);
        // SqlSession对象:内含访问数据库的所有API
        SqlSession sqlSession = ssFactory.openSession();
        // 执行查询
        User user = sqlSession.selectOne("user.getUserByid", 1);

        System.out.println(user);
        // 释放资源
        sqlSession.close();
    }
}

执行:


image.png
6.4 根据用户名模糊查询、添加用户

MybatisDemo1.java

package com.edp.mybatis.demo;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

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.Test;
import com.edp.mybatis.domain.User;
import com.edp.mybatis.utils.SqlSessionFactoryUtils;

public class MybatisDemo1 {

    @Test
    /**
     * 
     * @Title: testGetUserById
     * @Description: 查询所有用户
     * @param @throws IOException
     * @return void
     * @throws
     *
     */
    public void testGetUserById() throws IOException {
        // 创建SqlSessionFactoryBuilder类
        SqlSessionFactoryBuilder ssfBuilder = new SqlSessionFactoryBuilder();
        // Mybatis的工具类Resources
        // 创建核心配置文件的输入流
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 通过输入流创建SqlSessionFactory对象
        SqlSessionFactory ssFactory = ssfBuilder.build(resourceAsStream);
        // SqlSession对象:内含访问数据库的所有API
        SqlSession sqlSession = ssFactory.openSession();
        // 执行查询
        User user = sqlSession.selectOne("user.getUserByid", 1);

        System.out.println(user);
        // 释放资源
        sqlSession.close();

    }

    @Test
    /**
     * 
     * @Title: testGetUserByUserName
     * @Description: 模糊查询
     * @param 
     * @return void
     * @throws
     *
     */
    public void testGetUserByUserName() {
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
        // SqlSession对象:内含访问数据库的所有API
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 执行查询
        List userlist = sqlSession.selectList("user.getUserByUserName", "%张%");
        // List userlist = sqlSession.selectList("user.getUserByUserName", "张");

        for (User user : userlist) {
            System.out.println(user);
        }
        // 释放资源
        sqlSession.close();
    }
    
    
    @Test
    /**
     * 
     * @Title: testInsertUser
     * @Description: 添加(插入)用户
     * @param 
     * @return void
     * @throws
     *
     */
    public void testInsertUser() {
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
        // SqlSession对象:内含访问数据库的所有API
        SqlSession sqlSession = sqlSessionFactory.openSession();
//      SqlSession sqlSession = sqlSessionFactory.openSession(true);就自动commit
        // 执行添加
        User user =new User();
        user.setUsername("非晶体");
        user.setAddress("白菜市场");
        user.setSex("1");
        user.setBirthday(new Date());
        sqlSession.insert("user.insertUser",user);
        //一定要提交
        sqlSession.commit();

        // 释放资源
        sqlSession.close();
    }
    
    
    @Test
    /**
     * 
     * @Title: testUpdateUser
     * @Description: 更新用户
     * @param 
     * @return void
     * @throws
     *
     */
    public void testUpdateUser() {
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
        // SqlSession对象:内含访问数据库的所有API
        SqlSession sqlSession = sqlSessionFactory.openSession();
//      SqlSession sqlSession = sqlSessionFactory.openSession(true);就自动commit
        // 执行添加
        User user =new User();
        user.setId(10);
        user.setUsername("冬瓜太郎");
        sqlSession.update("user.updateUser",user);
        //一定要提交
        sqlSession.commit();

        // 释放资源
        sqlSession.close();
    }
    @Test
    /**
     * 
     * @Title: testDeleteUser
     * @Description: 删除用户
     * @param 
     * @return void
     * @throws
     *
     */
    public void testDeleteUser() {
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
        // SqlSession对象:内含访问数据库的所有API
        SqlSession sqlSession = sqlSessionFactory.openSession();
//      SqlSession sqlSession = sqlSessionFactory.openSession(true);就自动commit
        // 执行添加
        sqlSession.delete("user.deleteUser",30);
        //一定要提交
        sqlSession.commit();

        // 释放资源
        sqlSession.close();
    }
}

user.xml







    
    
    
    
    
    


    
    

    
    
    
        
        
        
        
        
        
        
        
        INSERT INTO `user`
        (`username`,
        `birthday`,
        `sex`,
        `address`)
        VALUES (#{username},
        #{birthday},
        #{sex},
        #{address});
    

    
    
    
        
        
        
        
        
        
            SELECT UUID()
        
        INSERT INTO `user`
        (`username`,
        `birthday`,
        `sex`,
        `address`)
        VALUES (#{username},
        #{birthday},
        #{sex},
        #{address});
    

    
    
        UPDATE `user`
        SET username = #{username}
        WHERE
        id = #{id}
    

    
    
        DELETE
        FROM `user`
        WHERE
        id = #{id}
    

7.0 Mybatis架构体系
image.png
8.0 Dao操作方式动态代理

动态代理开发规则 :只有接口,没有实现类

    1. namespace 必须是接口的全路径名称
    1. 接口的方法名必须与sql id一致
    1. 接口的入参必须与parameterType类型一致
    1. 接口的返回值必须与resultType类型一致

修改SqlMapConfig.xml




    

    ………………
    

    

    
    
    

UserMapper.xml










    
    
    
    
    
    


    
    

    
    
    
        
        
        
        
        
        
        
        
        INSERT INTO `user`
        (`username`,
        `birthday`,
        `sex`,
        `address`)
        VALUES (#{username},
        #{birthday},
        #{sex},
        #{address});
    

    
    
    
        UPDATE `user`
        SET username = #{username}
        WHERE
        id = #{id}
    


UserMapper.java

package com.edp.mybatis.mapper;

import java.util.List;

import com.edp.mybatis.domain.User;

/**
 * 
 * @Title: UserMapper.java
 * @Package com.edp.mybatis.mapper
 * @author EdPeng
 * @version 创建时间 2020年2月18日
 * @Description 用户信息持久化接口
 * @version V1.0
 */
public interface UserMapper {

    User getUserById(Integer id);

    List getUserByUserName(String userName);

    void updateUser(User user);
}

MybatisDemo2.java

package com.edp.mybatis.demo;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

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.Test;

import com.edp.mybatis.domain.User;
import com.edp.mybatis.mapper.UserMapper;
import com.edp.mybatis.utils.SqlSessionFactoryUtils;

/**
 * 
 * @Title: MybatisDemo2.java
 * @Package com.edp.mybatis.demo
 * @author EdPeng
 * @version 创建时间 2020年2月18日
 * @Description 动态Dao代理测试类
 * @version V1.0
 */
public class MybatisDemo2 {

    @Test
    /**
     * 
     * @Title: testGetUserById
     * @Description: 查询所有用户
     * @param @throws IOException
     * @return void
     * @throws
     *
     */
    public void testGetUserById() throws IOException {
        SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
        // 获取接口的代理实现类
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.getUserById(24);
        System.out.println(user);
        sqlSession.close();
    }

    @Test
    /**
     * 
     * @Title: testGetUserByUserName
     * @Description: 模糊查询
     * @param
     * @return void
     * @throws
     *
     */
    public void testGetUserByUserName() {
        SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
        // 获取接口的代理实现类
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List userList = userMapper.getUserByUserName("%张%");
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

    @Test
    /**
     * 
     * @Title: testInsertUser
     * @Description: 添加(插入)用户
     * @param
     * @return void
     * @throws
     *
     */
    public void testInsertUser() {
        SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
        // 获取接口的代理实现类
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user =new User();
        user.setId(29);
        user.setUsername("火钳刘明");
        userMapper.updateUser(user);
        
        sqlSession.commit();
        sqlSession.close();
    }

}

END

你可能感兴趣的:(【Java中级】30.0 SSM之Mybatis框架(一)——入门、增删查改、架构和动态代理Dao包装)