1.Mybatis的介绍

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

2.Mybatis的入门
2.1 准备sql数据
CREATE DATABASE `mybatis`;

USE `mybatis`;

CREATE TABLE `user`(
  `id` INT(20) NOT NULL PRIMARY KEY,
  `name` VARCHAR(30) DEFAULT NULL,
  `pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO `user`(`id`,`name`,`pwd`) VALUES 
(1,'王麻子','123456'),
(2,'张三','123456'),
(3,'李四','123890')
2.2 引入依赖(pom.xml)
      <dependencies>
        <!-- 导入依赖 -->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <!-- 数据库的版本一定要一致>
            <version>5.1.47</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>


    </dependencies>

2.3全局配置文件(mybatis-config.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>
    <environments default="development">
                <!-- 里面的每一个environment 代表一个具体环境-->
        <environment id="development">
                <!-- transactionManager 事物管理器-->
            <transactionManager type="JDBC"/>
                <!-- dataSource 数据源的配置-->
            <dataSource type="POOLED">
                <!-- 连接数据库的配置-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!-- resource 资源对应的路径-->
        <mapper resource="com/li/mapper/UserMapper.xml"/>
    </mappers>
</configuration>
2.4 编写mybatis 工具类
public class Utils {
        private static SqlSessionFactory sqlSessionFactory;
        static {
            try {
                //指定全局配置文件
                String resource = "mybatis-config.xml";
                //读取配置文件
                InputStream inputStream = Resources.getResourceAsStream(resource);
                //构建sqlSessionFactory
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //获取SqlSession
        public  static SqlSession getSession() {
            return sqlSessionFactory.openSession();
        }
}
2.5 实体类的编写

实体类用了lombo:
kLombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码。仅五个字符(@Data)就可以替换数百行代码从而产生干净,简洁且易于维护的Java类。
@Data: 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
@NoArgsConstructor: 注解在类,生成无参的构造方法。
@AllArgsConstructor: 注解在类,生成包含类中所有字段的构造方法。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String pwd;
    private String name;
}
2.6 操作用户的接口和UserMapper.xml文件
//操作用户的接口
public interface UserMapper {
    List<User> getUserList();
}
<?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">
<!--编写具体的sql namespace 命名空间 包名+接口名-->
<mapper namespace="com.li.mapper.UserMapper">
    <!-- id 与方法一致 resultType 结果类型具体到包名 -->
    <select id="getUserList" resultType="com.li.pojo.User">
    select * from user ;
  </select>
</mapper>
2.7 测试类
public class test {
    public static void main(String[] args) {
        //获得SqlSession对象
        SqlSession session = Utils.getSession();
        //通过session.getMapper()获得接口
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

测试结果:

User(id=1, pwd=123456, name=王麻子)
User(id=2, pwd=123456, name=张三)
User(id=3, pwd=123890, name=李四)

Process finished with exit code 0
2.8 包名层级的问题造成的错误

解决办法 :包名展开:一级一级建包
在这里插入图片描述
正确的目录结构:
在这里插入图片描述

3.CURD的操作及注意事项

对UserMapper接口进行编写CURD代码,代码如下:

//操作用户的接口
public interface UserMapper {
    List<User> getUserList();
    //根据用户的Id查询
    User selectById(int id);

    //多个参数的查询 必须加@Param(形参值)
    User selectByUsernamePwd(@Param("username") String username, @Param("pwd") String pwd);

    //新增用户
    int addUser(User user);

    //修改用户信息
    int updateUser(User user);

    //根据用户Id删除用户信息
    int deleteUserById(int id);
}

对UserMapper.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">
<!--编写具体的sql namespace 命名空间 包名+接口名-->
<mapper namespace="com.li.mapper.UserMapper">
    <!-- id 与方法一致 resultType 结果类型具体到包名 -->
    <select id="getUserList" resultType="com.li.pojo.User">
    select * from user ;
  </select>

    <select id="selectById" resultType="com.li.pojo.User">
        select * from user where id = #{id}
    </select>

    <select id="selectByUsernamePwd" resultType="com.li.pojo.User">
        select * from user where name = #{username} and pwd = #{pwd}
    </select>

   <insert id="addUser" parameterType="com.li.pojo.User">
       insert into `user`(`id`,`name`,`pwd`) values(#{id},#{name},#{pwd});
   </insert>

    <update id="updateUser" parameterType="com.li.pojo.User">
        update `user` set name = #{name}, pwd = #{pwd} where id = #{id};
    </update>

    <delete id="deleteUserById" parameterType="int">
        delete from user where id = #{id}
    </delete>
</mapper>

进行测试:

public class test {
    public static void main(String[] args) {
        //获得SqlSession 对象
        SqlSession session = Utils.getSession();
        //通过session.getMapper()获得接口
        UserMapper mapper = session.getMapper(UserMapper.class);
        //查询所有用户信息
        List<User> userList = mapper.getUserList();
        for (User user : userList) {
			 System.out.println(user);
			 }
        //根据用户id查询
        User user = mapper.selectById(1);
        System.out.println(user);

        //根据用户的姓名,密码查询
        User user1 = mapper.selectByUsernamePwd("张三", "123456");
        System.out.println(user1);

        
        //新增用户
        int res = mapper.addUser(new User(4, "刘德华", "19600808"));
        //提交事务
        session.commit();
        if (res > 0) {
            System.out.println("增加成功!");
        }


        //修改用户信息
        int res = mapper.updateUser(new User(4, "周星驰 ", "987654"));
        //提交事务
        session.commit();
        if (res > 0) {
            System.out.println("修改成功!");
        }

    
        //删除指定用户
        int res = mapper.deleteUserById(4);
        //提交事务
        session.commit();
        if (res > 0) {
            System.out.println("删除成功!");
        }


    }
}

注意事项:

1.增删改必须要提交事务
2.增删改没有返回值,查询有返回值
3.如果查询结果为null 说明字符集编码的问题
4.多个参数用@Param 注解

4.配置文件解析
1.mapper(映射器)
<!-- 绑定mapper配置文件的几种方式:-->
    <!-- 1.resource 资源对应的路径-->
    <!-- 2.class 接口对应的路径 UserMapper.xml UserMapper在同一包下 -->
    <!-- 3.package 接口很多可以扫描包 -->
    <mappers>
        <!--<mapper resource="com/li/mapper/UserMapper.xml"/>-->
        <!--<mapper class="com.li.mapper.UserMapper"/>-->
        <package name="com.li.mapper"/>
    </mappers>
2.properties (属性)
<!-- properties 属性读取外部资源-->
    <properties resource="db.properties"/>

外部资源:db.properties的配置

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8
username=root
password=123456
3.typeAliases(类型别名)
 <!--typeAliases 类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写-->
    <typeAliases>
        <!--<package name="com.li.pojo"/>-->
        <typeAlias type="com.li.pojo.User" alias="User"/>
    </typeAliases>

对应的UserMapper.xml 文件配置

<select id="selectById" resultType="User">
     select * from user where id = #{id}
 </select>
4.settings(设置)
<settings>
        <!-- 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。配置日志 查看具体sql信息,方便查错-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

注意: mybatis-config.xml 配置文件中有层级结构

在这里插入图片描述

5.结果映射

问题:如果sql中的列名与实体类的属性名不一致?如何解决?
方式一:设置列别名

 <select id="selectUserById" resultType="User">
       select id,name,pwd as password from user where id = #{id}
   </select>

方式二:结果映射 ResultMap

 <resultMap id="userResultMap" type="User">
        <!-- 主键一般使用id标签 其余使用result标签 -->
        <!--
        property 对应实体类的属性名
        column   对应数据库的列名
        -->
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="password" column="pwd"/>
    </resultMap>
    <select id="selectUserById" resultMap="userResultMap">
        select id,name,pwd from user where id = #{id}
    </select>
6.日志的配置
1.添加 Log4J 的 jar 包
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
2.配置 Log4J文件 创建一个名为 log4j.properties 的文件

### 设置###
log4j.rootLogger = debug,stdout,D,E
 
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
 
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = ./log/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
 
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =./log/error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
3.修改mybatis-config.xml 配置文件
<settings>
        <!-- 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。配置日志 查看具体sql信息,方便查错-->
        <setting name="logImpl" value="LOG4J"/>
    </settings>

打印结果:
在这里插入图片描述

4.如何使用log4j
public class Test2 {
    //注意导包的问题一定是  org.apache.log4j
    static Logger logger = Logger.getLogger(Test2.class);
    public static void main(String[] args) {
        //获取sqlsession
        SqlSession session = Utils.getSession();
        //获取接口的对象
        ResultMapper mapper = session.getMapper(ResultMapper.class);
        User user = mapper.selectUserById(1);
        logger.debug("This is a debug Message");
        logger.error("This is a error Message");
        logger.info("This is a info Message");
        System.out.println(user);
    }
}
7.分页操作

在学习mybatis等持久层框架的时候,会经常对数据进行增删改查操作,使用最多的是对数据库进行查询操作,如果查询大量数据的时候,我们往往使用分页进行查询,也就是每次处理小部分数据,这样对数据库压力就在可控范围内。

7.1 sql分页

分页接口

public interface ResultMapper {
    //分页操作
    List<User> selectUserByLimit(Map<String,Integer> map);
}

ResultMapper.xml文件

<select id="selectUserByLimit" parameterType="map" resultMap="userResultMap">
        select * from user limit #{startIndex}, #{PageSize}
</select>

测试

public class Test2 {
    //注意导包的问题一定是  org.apache.log4j
    static Logger logger = Logger.getLogger(Test2.class);
    public static void main(String[] args) {
        //获取sqlsession
        SqlSession session = Utils.getSession();
        //获取接口的对象
        ResultMapper mapper = session.getMapper(ResultMapper.class);
        int currentPage = 1;//第几页
        int PageSize = 2;//每页显示几个
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        map.put("startIndex",(currentPage-1)*PageSize);
        map.put("PageSize",PageSize);
        List<User> user = mapper.selectUserByLimit(map);
        for (User user1 : user) {
            System.out.println(user1);
        }

    }
}

打印结果
在这里插入图片描述

7.2Rowbounds分页

分页接口

public interface ResultMapper {
    //分页操作
    List<User> selectUserByLimit(Map<String,Integer> map);
}

ResultMapper.xml文件

 <select id="selectUserByLimit" parameterType="map" resultMap="userResultMap">
        select * from user ;
    </select>

测试

public class Test2 {
    //注意导包的问题一定是  org.apache.log4j
    static Logger logger = Logger.getLogger(Test2.class);
    public static void main(String[] args) {
        //获取sqlsession
        SqlSession session = Utils.getSession();
        int currentPage = 1;//第几页
        int PageSize = 2;//每页显示几个

        RowBounds rowBounds = new RowBounds((currentPage - 1) * PageSize, PageSize);
        List<User> user = session.selectList("com.li.mapper.ResultMapper.selectUserByLimit", null, rowBounds);
        for (User user1 : user) {
            System.out.println(user1);
        }
    }
}

打印结果
在这里插入图片描述
总结:一般错误都在于xml文件中sql语句的正确性.

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐