zoukankan      html  css  js  c++  java
  • Mybatis基础使用简介

    这几天把SSM框架整体整理了一遍,下面将三个系统分开阐述以下他们的基本实现方式,最后写一个整体的程序整合以下,

    首先是新建一个工程,因为暂时没有和Views有什么联系,我就新建了一个javaProject

    学习一个新的框架,首先是引入jar包

    mybatis框架所需要的jar包有

    mybatis-3.5.6.jar mysql-connector-java-5.1.47.jar

    上述两个包引入之后,我们新建一个conf.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> 
    
    <!-- 默认环境就是development -->
     <environments default="development">
     
            <environment id="development">
                <transactionManager type="JDBC"/>
                 <!-- 数据源 -->
                 <dataSource type="POOLED">
                     <property name="driver" value="com.jdbc.mysql.Driver"/>
                     <property name="url" value="jdbc:mysql://localhost:3306/jdbcdemo"/>
                     <property name="username" value="root"/>
                     <property name="password" value="root"/>
                 </dataSource>
            </environment>
     </environments>
    
    </configuration>

    这里面我们就配置mybatis需要使用的数据源以及驱动方式

    然后需要再数据库jdbcdemo新建一个表来满足我们测试的需要

    新建表如下:

    CREATE TABLE `person` (
      `id` int(11) DEFAULT NULL,
      `name` varchar(20) DEFAULT NULL,
      `age` int(11) DEFAULT NULL,
      `sex` int(11) DEFAULT NULL,
      `schoolAddress` varchar(200) DEFAULT NULL,
      `homeAddress` varchar(200) DEFAULT NULL,
      `comid` int(11) DEFAULT NULL,
      KEY `fk_p2c` (`comid`),
      CONSTRAINT `fk_p2c` FOREIGN KEY (`comid`) REFERENCES `company` (`comid`)
    )

    这里的一个外键连接是为以后的一对多测试,暂时不需要关注这个

    同时,我们需要在程序中配置该实体类,如下:

    package com.xjg.empty;
    
    import java.io.Serializable;
    
    public class Person implements Serializable {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private int id;
        private String name;
        private int age;
        private String stusex;
        private Address add;
        private int comid;
        private company com;
    
        public company getCom() {
            return com;
        }
    
        public void setCom(company com) {
            this.com = com;
        }
    
        public int getComid() {
            return comid;
        }
    
        public void setComid(int comid) {
            this.comid = comid;
        }
    
        public Person() {
        }
    
        public Person(int id, String name, int age, String stusex) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.stusex = stusex;
        }
    
        public Person(int id, String name, int age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }
    
        public Address getAdd() {
            return add;
        }
    
        public void setAdd(Address add) {
            this.add = add;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getStusex() {
            return stusex;
        }
    
        public void setStusex(String stusex) {
            this.stusex = stusex;
        }
    
        @Override
        public String toString() {
            return "Person [id=" + id + ", name=" + name + ", age=" + age + ", stusex=" + stusex;
        }
    
    }

    然后我们配置一个map文件,里面就写了我们需要用到的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="com.xjg.mapper.personMapper">
    
        <!-- 返回值类型 -->
        <resultMap type="person" id="permap">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="age" column="age"/>
            <result property="stusex" column="sex" javaType="String" jdbcType="INTEGER"/>
        </resultMap>
        
        
        <!-- CURD -->
      <!-- 通过传入的ID选择数据-->
    <select id="QueryById" resultMap="permap" parameterType="int" > select * from person where id = #{id} </select> </mapper>

    最后我们新建一个测试类,实现该方法

    package com.xjg.service;
    
    
    import java.io.IOException;
    import java.io.Reader;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    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.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.xjg.empty.Address;
    import com.xjg.empty.Person;
    import com.xjg.empty.PersonAndCompany;
    import com.xjg.empty.company;
    import com.xjg.empty.snoList;
    import com.xjg.mapper.personMapper;
    
    public class mybatisDemo {
    
        public static void mybatis01() throws IOException {
            
         //加载配置文件 Reader in
    = Resources.getResourceAsReader("conf.xml"); //获取sqlSession SqlSessionFactory sql = new SqlSessionFactoryBuilder().build(in); SqlSession stmt = sql.openSession(); //查询一个 Person per = stmt.selectOne("com.xjg.mapper.personMapper.QueryById", 1); System.out.println(per.toString());   stmt.close(); } public static void main(String[] args) throws Exception { mybatis01(); } }

    上述可以得到下面查询结果

    Person [id=1, name=zs, age=24, stusex=null

    上述与如果执行出错,可能是返回值类型出错,因为返回值我这里写的是person,这里需要在配置文件中添加下面这个默认属性,不然系统不认识person,并且需要将map文件加入到配置文件中

    在conf.xml添加

    <!-- 生成别名 -->
    <typeAliases>
        <!-- 
        <typeAlias type="com.xjg.empty.Person" alias="person"/>
         -->
         <package name="com.xjg.empty"/>
    </typeAliases>
     <!-- map文件 -->
     <mappers>
     <mapper resource="com/xjg/mapper/personMapper.xml"/>
     </mappers>

    这样你的返回值就可以使用person了

    上面在map文件中我们配置了一个resultMap标签,名字叫permap,如果我们的返回值只是person,那么可以在CURD那部分直接写person,但是我们还是配置了resultmap属性,主要目的是为了将person里面的stusex属性和表里的的sex属性对应,

    并且在表里面,该属性的类型是int,但是在程序中这个属性的类型的String,很明显,类型是不一致的,我在程序中传入的性别:男 是不可以直接存储到mysql中去的,这时我们就需要类型转换器来将我们的类型自动转换

    所以,我们先建一个类,然后继承BaseTypeHandler,代码如下:

    package com.xjg.change;
    
    import java.sql.CallableStatement;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import org.apache.ibatis.type.BaseTypeHandler;
    import org.apache.ibatis.type.JdbcType;
    import org.apache.ibatis.type.TypeHandler;
    
    public class Converter extends BaseTypeHandler<String> {
    
        //赋值转换
        @Override
        public void setNonNullParameter(PreparedStatement ps, int i, String  parameter, JdbcType jdbcType)
                throws SQLException {
            if(parameter=="男") {
                ps.setInt(i, 1);
            }
            else {
                ps.setInt(i, 0);
            }
            
        }
    
        //用列名获取结果并转换
        @Override
        public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
            return rs.getInt(columnName) == 1 ? "男":"女";
        }
    
        //用列下标获取结果并转换
        @Override
        public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
            return rs.getInt(columnIndex) == 1 ? "男":"女";
        }
    
        //存储过程或者函数获取结果并转换
        @Override
        public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
            return cs.getInt(columnIndex) == 1 ? "男":"女";
        }
    
    }

    然後我們需要(怎麽變繁體了,算了不管了)在conf.xml配置文件中添加轉換器配置

    <!-- 自定义类型转换器 -->
    <typeHandlers>
        <typeHandler handler="com.xjg.change.Converter" javaType="String" jdbcType="INTEGER"/>
    </typeHandlers>

    这样我们插入的男就可以在插入到数据库时变成1,然后再执行了、

    下面我们再简单说一下动态sql,再使用sql时,免不了需要使用很多的条件查询,这时我们就需要使用动态sql来编写出来我们的最终要执行的sql语句

    代码实现如下:

     <!-- 这里的parameterType无论是Stringint还是int[] 都可以正确执行 -->
          <select id="QuerySnoByIdWithArrayList" parameterType="int[]" resultMap="permap">
             select * from person 
             <where>
                 <if test="array.length>0 and array != null">
                  <foreach collection="array" open="id in(" close=")"  item="sno" separator="," >
                      #{sno}
                  </foreach>
                 </if>
             </where>
         </select>
         

    上面的语句效果是,基础查询时select * from person 如果参数存在,那么循环读取,拼接到where 条件中去,这样就实现了条件查询,

    上面我们写了这么多但是再调用的时候都是再XXmap.xml中根据id来直接调用,代码略显繁琐,我们可以添加一个接口方法,将所有实现的查询都集成到方法中去,注意,这里的接口名要和map文件的名字一样

    代码如下:

    package com.xjg.mapper;
    
    import java.util.List;
    import java.util.Map;
    
    import com.xjg.empty.Person;
    import com.xjg.empty.PersonAndCompany;
    import com.xjg.empty.company;
    import com.xjg.empty.snoList;
    
    public interface personMapper {
        Person QueryById(int id);
        
        
    }

    这样我们再调用的时候就可以直接使用这里面的方法了,代码如下

    public static void mybatisTest11() throws IOException {
            Reader in =    Resources.getResourceAsReader("conf.xml");
            SqlSessionFactory sql =  new SqlSessionFactoryBuilder().build(in);
            SqlSession stmt =  sql.openSession();
            personMapper pm =      stmt.getMapper(personMapper.class);
            List<Person> mm =  pm.QueryById(1);
            System.out.println(mm);
        }

    上边的数据源配置我们也可以单独提取出来,新建db.properties文件,内容如下

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/jdbcdemo
    username=root
    password=root

    然后我们再conf.xml文件中就可以引入该配置,如下:

    <environments default="development">
     <environment id="development">
             <transactionManager type="JDBC"/>
                 <!-- 数据源 -->
                 <dataSource type="POOLED">
                     <property name="driver" value="${driver}"/>
                     <property name="url" value="${url}"/>
                     <property name="username" value="${username}"/>
                     <property name="password" value="${password}"/>
                 </dataSource>
             </environment>
    </environments>

    下面时一对一和一对多测试

    在map.xml文件中添加如下代码

    <!-- 一对一 -->
         <select id="QuerySnoOneByOneOther" parameterType="int" resultMap="resMap3">
             select p.* ,c.* from person p inner join company c on p.comid=c.comid
             where p.id=#{id}
         </select>
         
          <resultMap type="person" id="resMap3">
             <result property="id" column="id"/>
             <result property="name" column="name"/>
             <result property="age" column="age"/>
             <result property="stusex" column="sex"/>
            <association property="com" javaType="company">
                <id property="comid" column="comid"/>
                <result property="comname" column="comname"/>
            </association>     
         </resultMap> 
         
         <!-- 一对多 -->
         <select id="QuerySnoOneToMore" parameterType="int" resultMap="resMap2">
             select c.*,p.* from person p 
             inner join company c on p.comid=c.comid where c.comid=#{id};
         </select>
         
         <resultMap type="company" id="resMap2">
             <id property="comid" column="comid"/> 
             <result property="comname" column="comname"/>
             <collection property="pp" ofType="person">
                 <result property="id" column="id"/>
                 <result property="name" column="name"/>
                 <result property="age" column="age"/>
                 <result property="stusex" column="sex"/>
             </collection>
         </resultMap>

    同时,我们需要在接口中添加对应方法

    List<PersonAndCompany> QuerySnoOneByOne(int a);
    List<company> QuerySnoOneToMore(int a);

    上述就实现了一对一和一对多,多对一和多对多时反过来的多对一和多个一对多

    有时候我们不需要一对一或者一对多的数据立刻加载出来,这就需要使用延迟加载,也叫懒加载

    实现如下:

    <!-- 一对多延迟加载 -->
         <select id="QuerySnoOneToMoreOnlazy" parameterType="int" resultMap="resMap4">
             select c.* from  company c  where c.comid=#{id};
         </select>
         
         <resultMap type="company" id="resMap4">
             <id property="comid" column="comid"/> 
             <result property="comname" column="comname"/>
             <collection property="pp" ofType="person" select="com.xjg.mapper.personComMapper.QueryStudentByComid" column="comid">
             </collection>
         </resultMap>
         

    这种方式需要在conf.中添加配置,如下

    <settings>
        <!-- 开启延迟加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 关闭立即加载 -->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

    有时候我们还需要引进缓存,mybatis自带一级缓存,并且默认开启

    需要我们添加应用,即在map.xml开启声明

    <!-- 开启缓存声明 -->
        <cache/>

    一级混缓存存储在SqlSession域中,只要该对象不关闭,缓存就可以一直用

    使用EhcacheCache三方缓存

    首先引入jar包

    ehcache-core-2.6.8.jar slf4j-api-1.7.30.jar aspectjrt-1.8.7.jar aspectjweaver-1.8.7.jar

    然后再map中引入二级缓存

        <cache type="org.mybatis.caches.ehcache.EhcacheCache">
        </cache>
        

    同时再conf.xml <settings>中开启二级缓存

    <!-- 开启二级缓存 -->
    <setting name="cacheEnabled" value="true"/>

    二级缓存存储再map域中,只要在相同map域中产生的SqlSession对象,都可以使用缓存内容

    一二级缓存均会在出现commit的之后失效

    或者

    <select id="QueryById" resultMap="permap" parameterType="int" useCache="true" flushCache="false">

    使用flushCache刷新缓存使其失效。

    以上就是简单的mybatis总结

  • 相关阅读:
    Java59道常见面试题,内附答案
    2020年一个月时间面试字节跳动,面试经历分享(已拿offer)
    阿里总结的《Java成神之路》 PDF 火了,完整版开放下载!
    Github14k堪称神级的Spring Boot手册,从基础入门到实战进阶
    三面阿里(支付宝)Java高开岗,复习两月有幸拿到offer
    Java 最常见的 200+ 面试题:面试必备
    【面试总结】终于拿到了美团offer了,没有辜负了这三个月的努力啊
    阿里P9都赞不绝口的面试宝典!半月看完25大专题,居然斩获阿里P7offer
    Integer是int
    抽象类和接口
  • 原文地址:https://www.cnblogs.com/aierben/p/14588255.html
Copyright © 2011-2022 走看看