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无论是String\int还是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总结

 

posted @ 2021-03-28 12:25  二五树  阅读(51)  评论(0编辑  收藏  举报