Mybatis-01-配置详解


SSM完整笔记

官网文档

一:为什么是Mybatis

  1. 什么是Mybatis:Mybatis是一款优秀的持久层框架,避免了几乎所有的JDBC代码和手动设置参数以及获取结果集的过程。可以使用简单的XML或注解来配置和映射原生信息,将接口和Java的实体类映射成数据库中的记录。
  2. 持久化:持久化是将程序数据在持久状态和顺势状态间转换的机制(因为内存空间小且断电失效,所以必须存在硬盘中)。
  3. Mybatis就是帮程序员在数据库中存取数据,传统的JDBC有很多重复代码,通过框架可以减少重复代码,提高开发效率。
  4. Mybatis优点:简单易学,灵活(sql写在xml里,便于统一管理和优化)

二:第一个Mybatis程序

  1. 搭建数据库(本项目使用MySql数据库)
CREATE DATABASE `mybatis`;

USE `mybatis`;

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
`id` int(20) NOT NULL,
`name` varchar(30) DEFAULT NULL,
`pwd` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert  into `user`(`id`,`name`,`pwd`) values (1,'王二','123456'),(2,'张三','abcdef'),(3,'李四','987654');
  1. Maven项目导入相关依赖
<dependency>
   <groupId>org.mybatis</groupId>
   <artifactId>mybatis</artifactId>
   <version>3.5.2</version>
</dependency>
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.47</version>
</dependency>
  1. 编写Mybatis核心配置文件,命名为Mybatis-config.xml文件,当然文件名可以自己修改,只需要在MybatisUtils类中加载的时候选择对应的名称即可。
<?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 id="development">
           <transactionManager type="JDBC"/>
           <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=utf8"/>
               <property name="username" value="root"/>
               <property name="password" value="123456"/>
           </dataSource>
       </environment>
   </environments>
   <mappers>
       <mapper resource="com/kuang/dao/userMapper.xml"/>
   </mappers>
</configuration>
  1. 编写Mybatis工具类(可以当作自己的一个工具,每次调用数据就获取sqlSession,当作数据库连接池中的连接对象使用)
public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    /*固定的三步,读取xml文件,从xml文件中构建sqlSessionFactory*/
    static {
        try {
            String resourse = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resourse);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*从sqlSessionFactory中获取sqlSession实例
    * sqlSession完全包含了面向数据库执行SQL命令所需的所有方法
    * */
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}
  1. 测试
    编写实体类和Mapper接口类
//这三个注解时lombok的,需要在idea中安装lombok插件,在项目中引入lombok依赖才能使用
//Data注解不需要手动写get,set,toString等方法
//AllArgsConstructor注解声明一个全部参数的构造器
//NoArgsConstructor注解声明一个无参构造器
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;
}
public interface UserMapper {
    /*获取全部用户*/
    List<User> getUserList();
}
  1. 编写Mapper.xml配置文件,namespace非常重要,一定要对应到对应的接口文件中,并且每写一个Mapper文件,就要在Mybatis-config.xml文件Mappers标签下配置一个mapper文件路径(有三种配置方式)。
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--namespace:绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.chelsea.dao.UserMapper">

    <!--select查询语句-->
    <!--id就相当于对应namespace中的方法名-->
    <!--resultType:sql语句中的返回值-->
    <select id="getUserList" resultType="com.com.chelsea.pojo.User">
        /*执行SQL语句*/
        select * from user
    </select>
</mapper>
  1. 测试
public class UserMapperTest {
    @Test
    public void test(){
        // 第一步:获得sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        // 第二步:方式一:使用Mapper映射方式执行sql
        //UserDao mapper = sqlSession.getMapper(UserDao.class);
        //List<User> userList = mapper.getUserList();
        // 第二步:方式二:不推荐使用
        List<User> userList = sqlSession.selectList("com.chelsea.dao.UserMapper.getUserList");
        for (User user:userList){
            System.out.println(user);
        }
        //关闭sqlSession
        sqlSession.close();
    }
}
  1. 可能出现的问题:静态资源过滤问题。如果UserMapper.xml文件没有写在Resource文件夹下,maven项目找不到此静态资源,则需要在pom文件中配置静态资源过滤问题,使得在java文件目录下的静态资源也可以被索引到。
<!--在build中配置resources,来防止我们资源导出失败的原因-->
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

三:Mybatis XML配置详解

Mybatis的第一个程序已经搭建完毕,其他的增删改查操作可根据情况自己编写,后续讲述其他部分内容。

  1. 引入外部配置文件,为了方便配置文件的管理,可以将数据库驱动,用户名密码,url等单独提出了,写在db.properties文件中,内容大致如下,之后在Mybatis的配置文件中引入此db.properties文件内容。(Mybatis中默认的事务管理器时JDBC,连接池默认为POOLED,除此之外还有c3p0等)
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8
<!--可以同时在mybatis配置文件和db.properties文件中配置数据源信息,如果同一个信息两处都配置,优先读取db.properties文件中信息。-->
<properties resource="db.properties">
    <property name="username" value="chelsea"/>
    <property name="password" value="han990713"/>
</properties>
  1. 引入别名
  • 别名是为Java类型设置一个短的名字,存在的意义仅在于用来减少类完全限定名的冗余
  • 两种方式:一种是直接为一个类写一个别名,另一种是可以直接扫描包
  • 其实还有第三种方式,通过注解来进行增加别名。在Myabtis的配置文件中配置别名信息如下,配置完成后在Mapper.xml文件中就可以不用使用全限定名:
<!--配置别名-->
<typeAliases>
    <!--第一种方式:为每个类进行别名配置-->
    <typeAlias type="com.chelsea.pojo.User" alias="user"/>
    <!--第二种方式:配置扫描包,在没有注解的情况下(优先使用注解),扫描包下的所有bean,默认为类名,首字母小写-->
    <package name="com.chelsea.pojo"/>
</typeAliases>
  1. 生命周期作用域
  • SqlSessionFactoryBuilder:一旦创建就不需要了,是一个局部变量
  • SqlSessionFactory:可以类似于数据库连接池,一旦创建就应该在应用运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 因此SqlSessioFactory的最佳作用域时应用作用域,最简单的使用就是单例模式或者静态单例模式
  • SqlSession:连接到连接池的一个请求,不是线程安全的,因此不能被共享,所以他的最佳作用域是请求或方法作用域,用完之后需要赶紧关闭,否则资源被占用。
  • 对应的代码如下:
public class MybatisUtils {

    private static SqlSessionFactory sqlSessionFactory;

    /*固定的三步,读取xml文件,从xml文件中构建sqlSessionFactory*/
    static {
        try {
            String resourse = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resourse);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*从sqlSessionFactory中获取sqlSession实例
    * sqlSession完全包含了面向数据库执行SQL命令所需的所有方法
    * */
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }
}

  1. ResultMap标签
  • 当属性名和字段名不一致时,查询结果可能为空:User{id=2, name=‘lovecd’, password=‘null’}。因为User属性为password,而非pwd,所以查询结果为空(sql语句为:select id,name,pwd from user where id = #{id})。
  • 解决方案1,起别名:select id,name,pwd as password from user where id = #{id}
  • 解决方案2,使用ResultMap映射:将数据库中的pwd映射为password,还有其他更奇葩的映射,可以放下面看一下。
<resultMap id="user" type="com.chelsea.pojo.User">  
   <result property="id" column="id"/>  
   <result property="name" column="name"/>  
   <result property="password" column="pwd"/>  
</resultMap>
  • 对于简单的语句根本不需要配置显示的结果映射,对于复杂一点的语句只需要描述他们的关系即可
  • 有时需要联表查询,就需要resultMap进行映射,举例如下:
<!-- 非常复杂的语句 -->
<select id="selectBlogDetails" resultMap="detailedBlogResultMap">
  select
       B.id as blog_id,
       B.title as blog_title,
       B.author_id as blog_author_id,
       A.id as author_id,
       A.username as author_username,
       A.password as author_password,
       A.email as author_email,
       A.bio as author_bio,
       A.favourite_section as author_favourite_section,
       P.id as post_id,
       P.blog_id as post_blog_id,
       P.author_id as post_author_id,
       P.created_on as post_created_on,
       P.section as post_section,
       P.subject as post_subject,
       P.draft as draft,
       P.body as post_body,
       C.id as comment_id,
       C.post_id as comment_post_id,
       C.name as comment_name,
       C.comment as comment_text,
       T.id as tag_id,
       T.name as tag_name
  from Blog B
       left outer join Author A on B.author_id = A.id
       left outer join Post P on B.id = P.blog_id
       left outer join Comment C on P.id = C.post_id
       left outer join Post_Tag PT on PT.post_id = P.id
       left outer join Tag T on PT.tag_id = T.id
  where B.id = #{id}
</select>
<resultMap id="detailedBlogResultMap" type="Blog">
  <constructor>
    <idArg column="blog_id" javaType="int"/>
  </constructor>
  <result property="title" column="blog_title"/>
  <association property="author" javaType="Author">
    <id property="id" column="author_id"/>
    <result property="username" column="author_username"/>
    <result property="password" column="author_password"/>
    <result property="email" column="author_email"/>
    <result property="bio" column="author_bio"/>
    <result property="favouriteSection" column="author_favourite_section"/>
  </association>
  <collection property="posts" ofType="Post">
    <id property="id" column="post_id"/>
    <result property="subject" column="post_subject"/>
    <association property="author" javaType="Author"/>
    <collection property="comments" ofType="Comment">
      <id property="id" column="comment_id"/>
    </collection>
    <collection property="tags" ofType="Tag" >
      <id property="id" column="tag_id"/>
    </collection>
    <discriminator javaType="int" column="draft">
      <case value="1" resultType="DraftPost"/>
    </discriminator>
  </collection>
</resultMap>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值