JavaEE Mybatis使用

1. Mybatis官网

下载地址
解压之后的内容:

JavaEE Mybatis使用_第1张图片
图1.png

Mybatis框架结构:


JavaEE Mybatis使用_第2张图片
图2.png

简要概述:

  • SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句,此文件需要在SqlMapConfig.xml中加载。
  • 通过mybatis环境等配置信息构造SqlSessionFactory(即会话工厂)。
  • 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
  • mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
  • MappedStatement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个MappedStatement对象,sql的id即是MappedStatement的id。
  • MappedStatement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过MappedStatement在执行sql前将输入的java对象映射至sql中,输入参数映射就是JDBC编程中对preparedStatement设置参数。
  • MappedStatement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过MappedStatement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于JDBC编程中对结果的解析处理过程。

2. 导入数据库表

1). 使用Navicat工具,在root上右键选择新建数据库

JavaEE Mybatis使用_第3张图片
图3.png

2). 新建数据库->确定
JavaEE Mybatis使用_第4张图片
图4.png

3). 打开数据库mybatis->在mybatis/表处单击右键选择运行SQL文件...
JavaEE Mybatis使用_第5张图片
图5.png

4). 选择桌面的sql文件->点击开始
JavaEE Mybatis使用_第6张图片
图6.png

mybatis.sql文件内容

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `orders`
-- ----------------------------
DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
  `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_orders_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 `orders` VALUES ('3', '1', '1000010', '2015-02-04 13:22:35', null);
INSERT INTO `orders` VALUES ('4', '1', '1000011', '2015-02-03 13:22:41', null);
INSERT INTO `orders` 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);

5). 导入成功后,刷新表,数据如下:


JavaEE Mybatis使用_第7张图片
图7.png

3. 测试

1). 创建新的Java工程,并导入Mybatis使用的java包,注意要导入对应的数据库驱动包(这里导入的是mysql-connector-java-5.1.42-bin.jar)


JavaEE Mybatis使用_第8张图片
图7.png

2). 在工程目录下创建一个源码包config,并在config包下创建sqlmap包、log4j.properties和SqlMapConfig.xml文件。


JavaEE Mybatis使用_第9张图片
图8.png

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%n

SqlMapConfig.xml文件内容




    
    
        
            
            
            
            
                
                
                
                
            
        
    

SqlMapConfig.xml是mybatis的核心配置文件,以上文件的配置内容为数据源、事务管理。
注意:等后面mybatis和Spring两个框架整合之后,environments的配置将被废除.
3). 创建一个po类--User
po类作为mybatis进行sql映射使用,po类通常与数据库表对应,User.java文件的内容如下:

public class User {
    // id
    private int id;
    // 用户名
    private String username;
    // 性别
    private String sex;
    // 用户名
    private Date birthday;
    // 地址
    private String address;
    public int getId() {
        return id;
    }
    public void setId(int 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 + "]";
    }
    
}

4). 在classpath下的sqlmap目录下创建sql映射文件user.xml
user.xml内容如下:






  • namespace:即命名空间,其用于隔离sql语句(即不同sql映射文件中的两个相同id的sql语句如何来区分)

5). 加载映射文件
mybatis框架需要加载映射文件,将user.xml添加在SqlMapConfig.xml中.
在SqlMapConfig.xml配置文件中添加配置信息:




    
    
        
            
            
            
            
                
                
                
                
            
        
    
    
    
    
        
        
    

6). 入门程序测试——根据id查询用户信息
I. user.xml映射文件中添加如下配置:




    
    

II. 编写MybatisTest类

public class MybatisTest {
    
    @Test
    public void testGetUserById() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(inputStream);
        // 4. 创建SqlSession对象
        SqlSession sqlSession = factory.openSession();
        // 5. 使用SqlSession对象执行查询,得到User对象
        // 第一个参数: 执行查询的StatementId,即配置文件user.xml中的id, 第二参数传入id对应的值
        User user = sqlSession.selectOne("getUserById", 10);
        // 6. 打印结果
        System.out.println(user);
        // 7. 释放资源
        sqlSession.close();
    }
}

III. 执行测试代码, 打印结果:


JavaEE Mybatis使用_第10张图片
图9.png

IV. 优化代码
一般来讲工厂对象一般在实际开发是单例的,并不需要频繁地创建

public class MybatisTest {
    private SqlSessionFactory factory;
    
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testGetUserById() {
        // 4. 创建SqlSession对象
        SqlSession sqlSession = factory.openSession();
        // 5. 使用SqlSession对象执行查询,得到User对象
        // 第一个参数: 执行查询的StatementId,即配置文件user.xml中的id, 第二参数传入id对应的值
        User user = sqlSession.selectOne("getUserById", 10);
        // 6. 打印结果
        System.out.println(user);
        // 7. 释放资源
        sqlSession.close();
    }

}

7). 根据用户名称模糊查询用户信息列表
I. user.xml文件添加



   
    
    

II. 编写测试方法

public class MybatisTest {
    private SqlSessionFactory factory;
    
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testGetUserByName() {
        SqlSession session = factory.openSession();
        List list = session.selectList("getUserByName", "%张%");
        for (User user : list) {
            System.out.println(user.toString());
        }
        session.close();
    }
}

III. 执行测试方法,打印结果:


JavaEE Mybatis使用_第11张图片
图10.png

IV. 另一个中不建议使用的占位符方式




        
    

测试代码:

public class MybatisTest {
    private SqlSessionFactory factory;
    
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testGetUserByName1() {
        SqlSession session = factory.openSession();
        List list = session.selectList("getUserByName1", "张");
        for (User user : list) {
            System.out.println(user.toString());
        }
        session.close();
    }

}

JavaEE Mybatis使用_第12张图片
图11.png

不推荐使用:原因容易引起SQL注入。

总结

---{}和${}

1). #{}:表示一个占位符号,可以很好地去避免sql注入。其原理是将占位符位置的整个参数和sql语句两部分提交给数据库,数据库去执行sql语句,去表中匹配所有的记录是否和整个参数是否一致。
#{}要获取输入参数的值:

  • 如果输入参数是简单数据类型,则#{}中可以写value或其它名称。
  • 如果输入参数是pojo对象类型,则#{}可通过OGNL方式去获取,表达式就是属性.属性.属性....方式。

2). ${}表示一个sql拼接符号,其原理是在向数据库发出sql之前去拼接好sql再提交给数据库执行。
${}要获取输入参数的值:

  • 如果输入参数是简单数据类型,则${}中只能写value。
  • 如果输入参数是pojo对象类型,则${}可通过OGNL方式去获取,表达式就是属性.属性.属性....方式。

一般情况下建议使用#{},特殊情况下必须要用${},比如:

1>. 动态拼接sql中动态组成排序字段,要通过${}将排序字段传入sql中。
2>. 动态拼接sql中动态组成表名,要通过${}将表名传入sql中。

---parameterType和resultType
  • parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼接在sql中。
  • resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。
---selectOne()和selectList()方法
  • selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常.
  • selectList可以查询一条或多条记录。

4. 其他操作

1). 插入数据
I. user.xml添加配置




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

如果输入参数是pojo,那么#{}中的名称就是pojo类中的属性(用到了对象图导航的思想)
II. 编写测试代码

public class MybatisTest {
    private SqlSessionFactory factory;
    
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testAddUser() {
        // 创建Session对象
        SqlSession session = factory.openSession();
        // 创建对象
        User user = new User();
        user.setUsername("mazaiting");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("科学院");
        
        // 插入数据
        session.insert("addUser", user);
        // 关闭Session
        session.close();
    }
}

III. 执行测试代码,打印结果:
可以看出虽然执行了sql语句,但是事务并没有提交,而是回滚了。


JavaEE Mybatis使用_第13张图片
图12.png

IV. 因此,应将测试代码修改为

public class MybatisTest {
    private SqlSessionFactory factory;
    
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    @Test
    public void testAddUser() {
        // 创建Session对象
        SqlSession session = factory.openSession();
        // 创建对象
        User user = new User();
        user.setUsername("mazaiting");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("科学院");
        
        // 插入数据
        session.insert("addUser", user);
        // 提交事务
        session.commit();
        // 关闭Session
        session.close();
    }

}

V. 执行单元测试,打印结果:


JavaEE Mybatis使用_第14张图片
图13.png

2). 自增主键返回

  • LAST_INSERT_ID():返回auto_increment自增列新记录id值。该函数是在当前事务下取到你最后生成的id值,而我们应知道查询操作是没有开启事务的,增删改操作是需要开启事务的。

I. 在user.xml中添加配置



   
    
    
        
            select LAST_INSERT_ID()
        
        insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    

  • keyProperty:返回的主键存储在pojo中的哪个属性(即其对应pojo的主键属性)。获取主键,实际上是将主键取出来之后封装到了pojo的主键属性当中。
  • resultType:返回的主键是什么类型(即其对应pojo的主键的数据类型)。
  • order:selectKey的执行顺序,是相对于insert语句来说的,由于mysql的自增原理,执行完insert语句之后才将主键生成,所以这里selectKey的执行顺序为AFTER。

II. 添加测试代码

public class MybatisTest {
    private SqlSessionFactory factory;
    
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testAddUser1() {
        // 创建Session对象
        SqlSession session = factory.openSession();
        // 创建对象
        User user = new User();
        user.setUsername("mazaiting");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("科学院");
        
        // 插入数据
        session.insert("addUser1", user);
        System.out.println("插入的id:" + user.getId());
        // 提交事务
        session.commit();
        // 关闭Session
        session.close();
    }
}

III. 执行测试代码,打印结果:


JavaEE Mybatis使用_第15张图片
图14.png

3). 删除用户
I. user.xml中添加删除语句




    
    
        delete from user where id = #{id}
    
    

II. 测试代码

public class MybatisTest {
    private SqlSessionFactory factory;
    
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    @Test
    public void testDeleteUser() {
        // 创建会话
        SqlSession session = factory.openSession();
        // 删除数据
        session.delete("deleteUser", 29);
        // 提交事务
        session.commit();
        // 关闭会话
        session.close();
    }

}

III. 打印结果:


JavaEE Mybatis使用_第16张图片
图15.png

4). 更新数据
I. user.xml添加配置



   
    
    
        update user set username = #{username} where id = #{id}
    

II. 测试代码

public class MybatisTest {
    private SqlSessionFactory factory;
    
    @Before
    public void init() throws IOException {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 2. 加载配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 3. 创建SqlSessionFactory对象
        factory = builder.build(inputStream);
    }
    
    public void testUpdateUser(){
        // 创建会话
        SqlSession session = factory.openSession();
        User user = new User();
        user.setId(10);
        user.setUsername("张某某");
        // 更新数据
        session.update("updateUser", user);
        // 提交事务
        session.commit();
        // 关闭会话
        session.close();
    }
}

III. 打印结果:


JavaEE Mybatis使用_第17张图片
图16.png

5. Mybatis与Hibernate不同

  • MyBatis学习成本低,入门门槛低。MyBatis需要程序员自己写sql,对sql修改和优化就比较灵活。MyBatis是不完全的ORM框架,MyBatis需要程序员编写sql,但是MyBatis也存在映射(输入映射、输出映射)适用场景:需求变化较快的项目开发,比如互联网项目、电商。
  • Hibernate学习成本高,入门门槛高,Hibernate是ORM框架,不需要程序员编写sql,自动根据对象映射生成sql。适用场景:需求固定的中小型项目,如OA系统、ERP系统。

代码下载

你可能感兴趣的:(JavaEE Mybatis使用)