Mybatis——最初的使用&与Spring整合

  • 时间:
  • 来源:互联网
  • 文章标签:

Mybatis

文章目录

  • Mybatis
    • 一. 基础
    • 二. demo
      • 1. 不与spring整合的Mybatis
        • 主xml
        • 子xml
        • xml映射器的更多写法
          • 多条数据——对象集合
          • 不想定义po怎么办
          • po对象中的一个属性是另一个po对象
            • 一个对多个
            • 一个对一个
      • 2. 与spring整合的Mybatis
        • 代替SqlSessionFactory连接数据库
        • 代替Mapper映射器
        • 在springMVC项目里面用起来

一. 基础

Mybatis时持久层框架,用来将关系型数据映射为对象(ORM)

在pom中导入Mybatis

 <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>

    <!--整合的中间jar包-->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.1</version>
    </dependency>

二. demo

首先接触到的是与springMVC框架连用的Mybatis。一顿操作猛如虎的写了个demo,但是发现自己理解的不好。没有办法,重新来过,看看单独的Mybatis到底是什么样子。

1. 不与spring整合的Mybatis

在看mybatis怎么配置之前,首先要看看它是怎么用的。mybatis的作用是将关系型数据映射为对象。我们想要在Java里面获得一个转换器,这个“转换器”能够将获得的结果集(一行一行的那种)转换为一个一个的java对象返回给我们。这个转换器就是mapper,学名叫映射器。

//userMapper就是“转换器”,通过sqlSession获得mapper接口对象。
UserinfomstMapper userMapper = sqlSession.getMapper(UserinfomstMapper.class);
//执行语句获得po
Userinfomst user = userMapper.selectByPrimaryKey(1);

如此我们就牢记,mybatis的核心目标是提供这个映射器对象给我们来使用。

那下面就看看,它是如何提供这些“转换器”mapper的:

根据jdbc的思路,与数据库进行交互主要就两步:1. 配置环境,连接数据库。2. 写sql,执行,获得结果。

而mybatis中的两个xml就是分别起了这两步的作用:

主xml

主xml的目的是告诉mybatis要连接的数据库是谁,它主要配置的是SqlSessionFactory的内容,我们要将配置的xml以字节流的形式传递给SqlSessionFactoryBuilder(工厂建造者),来获得SqlSessionFactory对象。

String resource = "Mybatis-config.xml";
InputStream inputStream = null;
try {
     inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
     e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

而通过SqlSessionFactory又可以获得SqlSession对象,真正的建立一个数据库连接。

SqlSession sqlSession = sqlSessionFactory.openSession();

主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 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>
    <mapper resource="mapper/UserInfomstMapper.xml"/>
  </mappers>
</configuration>

主xml中的mappers标签下,就是一个一个子xml的位置。我们需要在这里关联子xml,以后才能在sqlSession对象中获得我们的“映射器”对象。

子xml

子xml作为一个xml,本质也是一个配置文件,它配置的就是我们之前所提到的Mapper“转换器”。在这里面我们可以写sql语句,来获取我们想要的对象。

值得一提的是,Mapper“转换器”的获取与主xml的形式不同。主xml所配置的对象是以new的形式实例化的。而Mapper却是通过反射机制来获取对象的。

我们定义接口,在子xml中使用namespace属性来指名它配置的是哪个接口。接口的每个方法对应一个sql语句,在xml中用<select/update/delete/insert>标签配置每个方法对应的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 id="Base_Column_List" >
    id, phone, uname, password, sex, email, birthday, imgpath, cdate, lastlogintime, 
    rid
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from userinfomst
    where id = #{id,jdbcType=INTEGER}
</select>

当使用反射机制将接口类对象传入时,会自动搜索与这个接口相对应的xml文件,并实例化一个实现这个接口的对象。我们也因此获得了Mapper“转换器”。

UserinfomstMapper userMapper = sqlSession.getMapper(UserinfomstMapper.class);

获得转换器的我们就可以使用这个对象具有的方法来获取我们的数据,mybatis会为我们自动将获得的数据转换为我们自己定义的持久层(po)对象。

//执行语句获得po,Userinfomst为一个自定义的类
Userinfomst user = userMapper.selectByPrimaryKey(1);

xml映射器的更多写法

上面只是一个很简单的将一条数据映射为一个对象的例子。然鹅,实际情况下,我们很多时候需要获取的是多条数据,获得一个对象的集合。

多条数据——对象集合

接口配置:

List<Customer> findAllReturnCustomer();

子xml配置:

<select id="findByNameReturnCustomer" resultType="com.etc.pojo.Customer" parameterType="java.lang.String" >
    SELECT t1.uname as aname, t2.rname as bname, t4.name as cname, t4.path as namePath
    FROM UserInfomst t1, role t2, Role_Auth t3, authority t4
    WHERE t1.rid = t2.id AND  t2.id = t3.rid AND t3.aid = t4.id
</select>

哈,对于xml的配置和一个对象的获取是一样的有没有。我们只需要在resultType中写明集合内部对象的类别就可以了,想获得List就在接口声明返回对象是List就可以了。

不想定义po怎么办

使用HashMap作为返回值类型

接口:

List<HashMap> findByName(String name);

xml

<select id="findByName" resultType="java.util.HashMap" parameterType="java.lang.String" >
    SELECT *
    FROM userinfomst JOIN role ON role.id = userinfomst.rid
    WHERE userinfomst.uname = #{name};
</select>
po对象中的一个属性是另一个po对象
一个对多个

CustomerAu这么定义:

public class CustomerAu {

    private String aname;
    private String bname;
    private ArrayList<Au> aus;
}

Au这么定义:

public class Au {

    private String cname;
    private String namePath;
}

这个时候想要:

CustomerAu findOneToManyCustomer(String name);

xml需要用到resultMap标签,来将查询出来的数据整合,一条一条建立对象:

<resultMap id="customerAuMap" type="com.etc.pojo.CustomerAu">
    <id property="aname" column="uname"/>
    <result property="bname" column="rname"/>
    <collection property="aus" ofType="com.etc.pojo.Au">
      <id property="cname" column="name"/>
      <result property="namePath" column="path"/>
    </collection>
</resultMap>
<select id="findOneToManyCustomer" resultMap="customerAuMap" parameterType="java.lang.String" >
    SELECT t1.uname, t2.rname, t4.name , t4.path
    FROM UserInfomst t1, role t2, Role_Auth t3, authority t4
    WHERE t1.rid = t2.id AND  t2.id = t3.rid AND t3.aid = t4.id
    AND t1.uname= #{name}
</select>

collection标签内部包含的就是CustomerAu的aus属性。

一个对一个

CustomerAuOne这么定义

public class CustomerAuOne {

    private String aname;
    private String bname;
    private Au au;
}

每个CustomerAuOne中有一个Au对象,使用assocation标签。

<resultMap id="customerAuOneMap" type="com.etc.pojo.CustomerAuOne">
    <id property="aname" column="uname"/>
    <result property="bname" column="rname"/>
    <association property="au" javaType="com.etc.pojo.Au">
      <id property="cname" column="name"/>
      <result property="namePath" column="path"/>
    </association>
  </resultMap>
  <select id="findOneToOneCustomer" resultMap="customerAuOneMap" parameterType="java.lang.String" >
    SELECT t1.uname, t2.rname, t4.name , t4.path
    FROM UserInfomst t1, role t2, Role_Auth t3, authority t4
    WHERE t1.rid = t2.id AND  t2.id = t3.rid AND t3.aid = t4.id
    AND t1.uname= #{name}
  </select>

2. 与spring整合的Mybatis

Spring框架是管理对象依赖关系的容器,它整合Mybatis的方式是将它其中涉及到的对象使用容器管理。回忆Mybatis中涉及到的对象有两种,一种是用于获得数据库连接的SqlSessionFactory等类,一种是映射器Mapper等对象。

首先需要在tomcat中注册Spring容器:

	<!--  声明另一个spring容器-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:springContext.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

classpath指向等内容就是我们要注册的容器的xml配置文件。

[有关context-param标签:https://my.oschina.net/u/3045515/blog/1586882]

这个容器将与SpringMVC容器区分开(其实可以和在一起的)

在spring容器对应的springContext.xml文件中,我们将装配Mybatis相关的对象。

代替SqlSessionFactory连接数据库

<!--    这里就相当于单独写Mybatis时的主xml的作用——配置环境&注册Mapper-->
    <bean id="sqlSessionFactoryMy" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--        将连接池关联到数据源属性上-->
        <property name="dataSource" ref="dataSource"/>
        <!--        注册子Mapper-->
        <property name="mapperLocations" value="classpath*:mappers/*Mapper.xml"  />
    </bean>

用于与spring进行整合的类变成SqlSessionFactoryBean了。这段代码装配了Id为sqlSessionFactoryMy的数据库连接类。使用的数据源为dataSource对象。

dataSource对象的装配如下:

<!--    使用数据连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${mysql.url}"/>
        <property name="username" value="${mysql.username}"/>
        <property name="password" value="${mysql.password}"/>
        <!--        还有其他属性如maxActive表示最大连接数-->
    </bean>

为了使用${mysql.password}这种引用,需要引入:

<context:property-placeholder location="classpath:jdbc.properties" ignore-unresolvable="true"/>

这部分内容就相当于不与Spring进行整合的主xml文件配置的内容。

代替Mapper映射器

<!--    代替子xml,进行接口扫描,装配Mapper接口对象-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--指定会话工厂,如果当前上下文中只定义了一个则该属性可省去 -->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryMy"/>
        <!-- 指定要自动扫描接口的基础包,实现接口 -->
        <property name="basePackage" value="com.etc.web.dao"/>
    </bean>

在这里,使用MapperScannerConfigurer类扫描Mapper接口。MapperScannerConfigurer类装配到spring容器里后,会将扫描到的Mapper接口对象也装配到Spring容器里面。因此,记得在Mapper接口对象上使用注解,表示这个是个组件:

@Repository
//@Mapper
public interface UserMapper {

    @Select("select id,uname from userinfomst where uname = #{name}")
    User selectByName(String name);
}

使用@Repository或者@Mapper标签都行,它们本质上都是@Component标签。

在这里使用了@Select注解来配置这个方法,也可以继续使用子xml文件配置。

此时我的子xml文件,只用了标签mapper,写明了命名空间。

<?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.etc.web.dao.UserMapper">
</mapper>

到这里我们就已经达到了最初目的——获得可以将关系数据映射为对象的Mapper(映射器)。

在springMVC项目里面用起来

将整个流程捋一捋,我们现在可以通过映射器获取po持久层对象了。在遇到请求到时候,可以将信息返还给前端了。

但在controller中很少有人直接使用Mapper(属于dao层),一般中间都会加一层Service层。

定义Service接口:

public interface UserService {
    User getByName(String name);
}

实现Service接口:

@Service
public class UserServiceImp implements UserService {

    // 注入mapper,由代理MapperScanenrConfig配置完成
    @Autowired
    UserMapper userMapper;

    @Override
    public User getByName(String name) {
        return userMapper.selectByName(name);
    }
}

记得加上@Service,让它也能被自动注入,在Controller层愉快的使用。

本文链接http://www.taodudu.cc/news/show-83017.html