MyBatis基本配置和实践

第一步:创建Java工程和实验数据库

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);

第二步:加入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>12-mybatis</artifactId>
        <groupId>com.itheima</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>mybatis0523</artifactId>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>
    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

</project>

第三步:在resources目录下加入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

第四步:在resources目录下加入SqlMapConfig.xml(MyBatis核心配置文件)

<?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>

    <!--定义properties文件供property标签调用-->
    <properties resource="db.properties"/>

    <typeAliases>
        <!--使用包扫描的方式批量定义别名, 别名等于短类名且不区分大小写, 但建议以首字母小写的驼峰命名法的方式使用别名-->
        <package name="cn.itheima.pojo"/>
    </typeAliases>

    <!-- 和spring整合后 environments配置将废除-->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理-->
            <transactionManager type="JDBC"/>
            <!-- 使用MyBatis默认的数据库连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="Users.xml"/>
        <package name="cn.itheima.mapper"/>
        <!--使用包扫描的方式批量引入Mapper接口: 接口名称和映射文件名称除扩展名外要完全相同; 接口和映射文件必须放在同一个目录中-->
    </mappers>

</configuration>

第五步:pojo类

package cn.itheima.pojo;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {
    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 + "]";
    }

}

第六步:在resources目录下加入Users.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="test">

    <!-- 根据id获取用户信息 -->
    <select id="findUserById" parameterType="int" resultType="cn.itheima.pojo.User">
        select * from user where id = #{id}
    </select>

    <select id="findUserByUsername" parameterType="string" resultType="cn.itheima.pojo.User">
        SELECT * FROM user WHERE username LIKE #{value}
        <!-- 功能上等价于
        SELECT * FROM user WHERE username LIKE ‘${value}‘
        -->
    </select>

    <!--
    #{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。
    #{}可以接收简单类型值或pojo属性值。如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

    ${}表示拼接sql串,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换,
    ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。
    -->

    <insert id="insertUser" parameterType="cn.itheima.pojo.User">
        <selectKey order="AFTER" resultType="java.lang.Integer" keyProperty="id">
            SELECT LAST_INSERT_ID()
        </selectKey>
        INSERT INTO user(username,birthday,sex,address)VALUES (#{username},#{birthday},#{sex},#{address})
    </insert>

    <delete id="deleteUserById" parameterType="int">
        DELETE FROM user WHERE id = #{id}
    </delete>

    <update id="updateUser" parameterType="cn.itheima.pojo.User">
        UPDATE user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} WHERE id=#{id}
    </update>

</mapper>

第七步:在SqlMapConfig.xml中配置Users.xml(在核心配置文件中加载sql映射文件)

    <mappers>
        <mapper resource="Users.xml"/>
        <!--第一个实验中只用到了第一行设置-->
        <package name="cn.itheima.mapper"/>
        <!--使用包扫描的方式批量引入Mapper接口: 接口名称和映射文件名称除扩展名外要完全相同; 接口和映射文件必须放在同一个目录中-->
    </mappers>

第八步:单元测试

package cn.itheima.test;

import cn.itheima.pojo.User;
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 java.io.InputStream;
import java.sql.*;
import java.util.List;

/**
 * Created by Eric on 3/10/17.
 */
public class UserTest {

    /**
     * 使用MyBatis进行数据库操作
     */
    @Test
    public void findUserById() throws Exception {
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession openSession = sqlSessionFactory.openSession();

        User user = openSession.selectOne("test.findUserById", 10);

        System.out.println(user);
        openSession.close();
    }

    @Test
    public void findUserByUsername() throws Exception {
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        List<User> userList = sqlSession.selectList("test.findUserByUsername", "%王%");

        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

    @Test
    public void insert() throws Exception {
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        User user = new User();
        user.setUsername("小明");
        user.setAddress("荷兰");
        user.setSex("1");

        sqlSession.insert("test.insertUser", user);

        sqlSession.commit();
        System.out.println("插入完成, 插入纪录的主键ID为: " + user.getId());
        sqlSession.close();
    }

    @Test
    public void delete() throws Exception {
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        sqlSession.delete("test.deleteUserById", 29);

        sqlSession.commit();
    }

    @Test
    public void update() throws Exception {
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 先查找纪录, 再修改纪录
        User user = sqlSession.selectOne("test.findUserById", 16);
        user.setAddress("荷兰");

        sqlSession.update("test.updateUser", user);

        sqlSession.commit();
    }

    /**
     * 使用JDBC方式进行数据库操作
     */
    @Test
    public void jdbc() {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            //加载数据库驱动
            Class.forName("com.mysql.jdbc.Driver");
            //通过驱动管理类获取数据库链接
            connection = DriverManager.getConnection("jdbc:mysql://172.28.128.5:3306/mybatis?characterEncoding=utf-8", "ttsc", "redhat");
            //定义sql语句 ?表示占位符
            String sql = "select * from user where username = ?";
            //获取预处理statement
            preparedStatement = connection.prepareStatement(sql);
            //设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
            preparedStatement.setString(1, "王五");
            //向数据库发出sql执行查询,查询出结果集
            resultSet = preparedStatement.executeQuery();
            //遍历查询结果集
            while (resultSet.next()) {
                System.out.println(resultSet.getString("id") + "  " + resultSet.getString("username"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //释放资源
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

小结一:selectOne和selectList的区别是什么?

1、selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常:
org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
    at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)

2、selectList可以查询一条或多条记录。

小结二:如果不同于例子中的自增主键ID,而采用UUID该如何操作?

<!--需要增加通过select uuid()得到uuid值,注意这里使用的order是“BEFORE”-->
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
    <selectKey resultType="java.lang.String" order="BEFORE" keyProperty="id">
        select uuid()
    </selectKey>
    insert into user(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>

小结三:Mybatis解决jdbc编程的哪些问题?

1、数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
    解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。
2、Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
    解决:将Sql语句配置在mapper映射文件中,与java代码分离。
3、向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
    解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。
4、对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
    解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。

小结四:mybatis与hibernate有哪些不同?

1、Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。

2、Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。

3、Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。

总结:

1、如果没有引入junit,Test目录下JDBC单元测试会报无法找到com.mysql.jdbc.Driver

2、如果没有在pom.xml中设置build标签进行属性文件拷贝, 那么在resources目录下的配置文件在编译时将不会被复制到classpath路径下

3、如果没有引入slf4j(一种log4j的具体实现类), 即使配置了log4j.properties也看不到MyBatis的日志输出.

4、最终的目录结构为:resources下有db.properties/log4j.properties/SqlMapConfig.xml/Users.xml共4个文件(db.properties未放出),和cn.itheima.pojo路径下的User.java一个。
时间: 2024-10-12 12:47:19

MyBatis基本配置和实践的相关文章

MyBatis基本配置和实践(五)

第一步:创建一个Maven工程 第二步:编辑Maven工程的pom.xml,引入mybatis-generator-maven-plugin <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instan

MyBatis基本配置和实践(二)

一.前言 从上一篇文章的junit单元测试环节可以看到,每一次调用MyBatis需要先加载SqlMapConfig.xml文件,再通过SqlSessionFactoryBuilder创建SqlSessionFactory,然后从SqlSessionFactory获取SqlSession,最后调用SqlSession的selectOne.selectList.insert.delete方法完成数据库操作,编码效率低下. 二.若干概念的解释 1.SqlSession的使用范围 SqlSession中

笔记:MyBatis XML配置详解

MyBatis 的配置文件包含了影响 MyBatis 行为甚深的设置(settings)和属性(properties)信息.文档的顶层结构如下: configuration 配置 properties 属性 settings 设置 typeAliases 类型命名 typeHandlers 类型处理器 objectFactory 对象工厂 plugins 插件 environments 环境 environment 环境变量 transactionManager 事务管理器 dataSource

Mybatis基本配置(一)

1. Mybatis介绍 MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录. 2. 准备jar包 1)mybatis-3.3.0.jar, Mybatis包. 2)sqljdbc4.jar ,因为我们要用到SQLS

hao947 : Mybatis resultMap配置插入和主键自增返回 : 好947

映射配置文件  好947  <!-- type:映射实体类的数据类型 id:resultMap的唯一标识 -->  <resultMap type="person" id="BaseResultMap">   <!-- column:库表的字段名 property:实体类里的属性名 -->   <id column="person_id" property="personId" /&g

MyBatis MapperScannerConfigurer配置――MyBatis学习笔记之八

MyBatis MapperScannerConfigurer配置——MyBatis学习笔记之八 2012-09-02 20:01:42 标签:Spring MyBatis MapperScannerConfigurer bean默认命名 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://legend2011.blog.51cto.com/3018495/980150 在上一篇博文的示例中,我们在beans.xml中配置了stu

spring和mybatis整合配置

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p&

springmvc+spring+mybatis+mysql配置过程

环境:eclipse 项目目录: jar包: web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http:/

Mybatis中配置Mapper的方法

Mybatis中配置Mapper的方法 在这篇文章中我主要想讲一下Mybatis配置文件中mappers元素的配置.关于基础部分的内容可以参考http://blog.csdn.net/elim168/article/details/40622491. 我们知道在Mybatis中定义Mapper信息有两种方式,一种是利用xml写一个对应的包含Mapper信息的配置文件:另一种就是定义一个Mapper接口,然后定义一些相应的操作方法,再辅以相应的操作注解. 现假设我有这样一个实体类: Java代码