Mybatis入门

Mybatis是一个ORM框架,通常作为SSM中的M,可以与Spring集成搭建相应的项目。

001、依赖

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

002、入门

Mybatis也是可以使用注解驱动和配置文件驱动的,再次使用配置文件测试。

首先用一个实体类对应数据库中的表。

package pojo;

public class City {
    private int city_id;
    private int pro_id;
    private String name;

    public City(){};

    public City(int city_id, int pro_id, String name) {
        this.city_id = city_id;
        this.pro_id = pro_id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "City{" +
                "city_id=" + city_id +
                ", pro_id=" + pro_id +
                ", name='" + name + '\'' +
                '}';
    }
}

一个Mybatis整体配置文件。

<?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>
    <!--这是一个资源文件,下文$中取出的就是该文件中的数据-->
    <properties resource="mysql.properties"/>
    <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>
    
    <mappers>
        <!--Map映射文件,里面是用来写Sql的-->
        <mapper resource="mapper/mapper.xml"/>
    </mappers>
</configuration>

一个Mapper映射文件,里面用于写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="cityMapper">
    <select id="selectMap" parameterType="int" resultType="pojo.City">
    select * from city where city_id  &lt;${id}
  </select>
</mapper>

此时通过SqlSession等获取到数据。

@Test
public void test() throws Exception{
    String resource = "mybatis.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);	
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    try(SqlSession sqlSession = sqlSessionFactory.openSession()) {
        List<City> city = sqlSession.selectList("cityMapper.selectMap", 130800);
        final Iterator<City> iterator = city.iterator();

        while(iterator.hasNext())
             System.out.println(iterator.next());
        }


    }

003、SqlSession

一个SqlSession的出现有以下三个类处理。

SqlSessionFactoryBuilder

建造器,通过资源获取到SqlSessionFactory,此后基本没用。

建造者。

SqlSessionFactory

用于生产SqlSession.

工厂。

SqlSession

一个会话,通过会话处理各种sql语句。

Mybatis也可不使用Mapper的xml配置,转而使用注解。

如下用来代替映射文件的xml.

public interface MapperCity {

    @Select("select * from city where city_id<${id}")
    List<City> selectCitys(int id);
}

在mybatis.xml整体配置的mapper加入类名即可。

<mappers>
        <mapper resource="mapper/mapper.xml"/>
        <mapper class="mapper.MapperCity"/>
    </mappers>

测试一下:

public class MapTest {

    SqlSession sqlSession;

    @Before
    public void open() throws IOException {
        String resource = "mybatis.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        sqlSession = sqlSessionFactory.openSession();
    }

    @After
    public void close(){
        sqlSession.close();;
    }


    @Test
    public void test01(){
        final MapperCity mapper = sqlSession.getMapper(MapperCity.class);
        final List<City> cities = mapper.selectCitys(120700);

        for(City city:cities){
            System.out.println(city);
        }
    }
}

004、接口和xml的组合

有时候sql语句比较复杂的时候,也经常使用接口和xml的组合,即通过接口提供一组api,由xml具体实现。

这样在执行服务的时候,通过接口获取的对象也可以调用xml中的sql。

接口只有提供的方法。

package mapper;

//此处接口名就是xml中namespace,方法名就是语句id
public interface SelectCity {

    City selectOne(int id);

    List<City> selectList(int id);
}

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">
<mapper namespace="mapper.SelectCity">
    <select id="selectOne" parameterType="int" resultType="pojo.City">
    select * from city where city_id=${id}
  </select>

    <select id="selectList" parameterType="int" resultType="pojo.City">
        select * from city where city_id  &lt;${id}
    </select>
</mapper>

mybatis全局配置中需要这个mapper:

<mapper resource="mapper/SelectCity.xml"/>

执行查询:

final SelectCity mapper = sqlSession.getMapper(SelectCity.class);
final City city = mapper.selectOne(110100);
System.out.println(city);

005、全局xml配置

全局配置文件中有些标签比较常用。

properties

可以从外部加载properties文件,或者在子标签中配置属性。

<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>
settings

相关配置信息,使用缓存等,懒加载等。

<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
typeAliases

别名

<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
  <typeAlias alias="Comment" type="domain.blog.Comment"/>
  <typeAlias alias="Post" type="domain.blog.Post"/>
  <typeAlias alias="Section" type="domain.blog.Section"/>
  <typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
mappers

有mapper等子标签,也可以直接使用包。

<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <package name="org.mybatis.builder"/>
</mappers>

006、映射xml配置

映射xml中有许多子标签。

select、update、insert、delete.............
sql、cache、resultMap。。。。。

有些重要的属性:

id	在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType	将会传入这条语句的参数类的完全限定名或别名。这个属性是可选的,因为 MyBatis 可以通过 
resultType	从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。
resultMap	外部 resultMap 的命名引用。结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复杂映射的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同时使用。
1、parameterType

参数类型,Mybatis对参数类型起了别名,有些类型如int也是别名。

这个属性中的值通常就是sql语句的参数类型,这里的类型要和传入的类型对应,否则报错。

<select id="selectMap" parameterType="int" resultType="pojo.City">
        select * from city where city_id  &lt;${id}
  </select>

也可以使用map做映射,如下第三节。

2、$/#的区别
3、map

这个map是入参parameterType的可选值之一,别和resultMap搞混。

给字段起别名,可以通过map进行映射。

Map<Object,Integer> map=new HashMap();
map.put("id",130800); //此处的map的key就是xml中的参数
List<City> list = sqlSession.selectList("cityMap.selectMap", map);
<select id="selectMap" parameterType="map" resultType="pojo.City">
    select * from city where city_id  &lt;${id}; <!-- 此处的id是map的key>
  </select>
4、resultType

从这条语句中返回的期望类型的类的完全限定名或别名。注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。使用 resultType 或 resultMap,但不能同时使用。

5、resultMap

这也是用来做映射的,类和数据库进行映射。

如果返回的类型和类的字段类型不同,使用resultMap进行处理。

class			database

c_id 			city_id
p_id			pro_id
name			name

Citys类

package pojo;

public class Citys {
    private int c_id;
    private int p_id;
    private String name;

    public Citys(){};

    @Override
    public String toString() {
        return "Citys{" +
                "c_id=" + c_id +
                ", p_id=" + p_id +
                ", name='" + name + '\'' +
                '}';
    }
}

xml配置

<select id="resMap" parameterType="map" resultMap="c_map">
        select * from city where city_id  &lt;${id};
    </select>

    <resultMap id="c_map" type="pojo.Citys">
        <result property="c_id" column="city_id"/>
        <result property="p_id" column="pro_id"/>
    </resultMap>

测试类:

	@Test
    public void test04(){
        Map<Object,Integer> map=new HashMap();
        map.put("id",130800);
        final List<Citys> list = sqlSession.selectList("cityMap.resMap", map);
        for(Citys city:list){
            System.out.println(city);
        }
    }

resultMap有好几个子标签,如result、association等。

association用于处理复杂字段。

<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>

constructor - 类在实例化时,用来注入结果到构造方法中

idArg - ID 参数;标记结果作为 ID 可以帮助提高整体效能

arg - 注入到构造方法的一个普通结果

6、mybatis返回map
Map selectList(User user);

<select id="selectOne"  parameterType="cn.lyn4ever.entity.User"  parameterType="cn.lyn4ever.entity.User"   resultType="java.util.HashMap">
       select id,username,telphone from user where telphone=#{telphone} and password = #{password}
    </select>

上这结果就是说,以User类的属性名为key,属性值为value。
当然,也可以查出来多条记录,将这个Map放进List中

List<Map> selectList(User user);

<select id="selectOne"  parameterType="cn.lyn4ever.entity.User"  resultType="java.util.HashMap">
       select id,username,telphone from user
    </select>


    
 但是有时候我们想要这种结果,怎么办呢?

{
	"01":{
		username:"zhangsan",
		telphone:"13000000000"
	}
}

也就是我们要自定义一个Map<String,User>,这样的话,有以下两种解决方法:
1.使用注解

    @MapKey("id")
    Map<String,User> getUserInMap();

    <!--xml和之前写法一样-->
    <select id="getUserInMap" parameterType="cn.lyn4ever.entity.User"   resultType="User">
       select id,username,telphone from user where telphone=#{telphone} and password = #{password}
    </select>

    这个@MapKey的value写的就是User对象的一个属性
    
    
2.在xml文件中写上

     HashMap<String,Object> getUserInMap();

    <select id="getUserInMap" parameterType="cn.lyn4ever.entity.User"   resultType="java.util.HashMap">
    SELECT id as 'key', * as 'value', id,username,telphone from user where telphone=#{telphone} and password = #{password}
    </select>

当然以上这两种方法,如果查出来是多条的话也会是List的形式,如下:
    
    /**
     *
     * @param office
     * @return 总数
     */

    List<HashMap<String,Integer>> countByOffice();

    <select id="countByOffice" resultType="java.util.HashMap" >
        select office as 'key' ,count(1) as 'value' from doctor group by office
    </select>
7、调用存储过程
<select id="queryEmp" parameterType="map" statementType="CALLABLE">
    {
        call pag_add(
            #{p1,mode=IN,jdbcType=NUMERIC},
            #{p2,mode=IN,jdbcType=NUMERIC},
            #{p3,mode=OUT,jdbcType=NUMERIC}
        )
    }
    </select>
posted @ 2020-12-28 09:58  cgl_dong  阅读(91)  评论(0编辑  收藏  举报