Mybatis入门及讲解

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语句的正确性.

猜你喜欢

转载自blog.csdn.net/lirui1212/article/details/105749425