mybatis初始化

一、mybatis使用方式

mybatis使用需要创建SqlSessionFactory,创建方式有两种:

  1. 通过mybatis自己提供的SqlSessionFactoryBuilder创建:
    1.1通过代码创建,不需要配置xml
public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        //配置Java Mapper文件的包名
        configuration.addMappers("com.xiaolong.dao");
        Environment environment = new Environment("dev",new ManagedTransactionFactory(),dataSource());
        configuration.setEnvironment(environment);

        
        return builder.build(configuration);
    }

1.2 通过配置文件configration.xml创建:

public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        return builder.build(Resources.getResourceAsReader("mybatisConfig.xml"));
    }

mybatisConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false" />
                <property name="username" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
    	//配置mapper文件
        <mapper resource="mappers/studentMapper.xml"/>

    </mappers>
</configuration>

2.通过spring创建,mybatis-spring.jar提供了SqlSessionFactoryBean

   @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        //configuration配置文件
        ClassPathResource classPathResource = new ClassPathResource("mybatisConfig.xml");
        sqlSessionFactoryBean.setConfigLocation(classPathResource);
        sqlSessionFactoryBean.setDataSource(dataSource());
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        (1)扫描mapper.xml的路径
        Resource[] resources = resolver.getResources("classpath*:*Mapper.xml");
        sqlSessionFactoryBean.setMapperLocations(resources);

        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBean.getObject();
        (2)扫描java Mapper类的路劲
        sqlSessionFactory.getConfiguration().addMappers("com.xiaolong.dao");
        return sqlSessionFactory;
    }

(1)和(2)时配置Mapper文件的两种方式,第一种方式是直接扫描xml
文件,xml文件的路劲可以随便配置,而不需要java文件,第二种方式是配置java Mapper,通过Java Mappper 找到的mapper.xml

(1)第一种使用方式
studentMapper.xml

<?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.xiaolong.dao.StudentDao">
    <select id="selectById" parameterType="int" resultType="com.xiaolong.dto.Student">
        select * from t_student where id = #{id}
    </select>

</mapper>

使用

@Transactional
@Service
public class MybatisStudentService {

    @Autowired
    SqlSessionFactory sqlSessionFactory;

    /**
     * 使用xml方式,无Java dao文件
     * @param id
     * @return
     */
    public Student selectById(int id){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //通过字符串获取xml里的方法
        Student student = sqlSession.selectOne("com.xiaolong.dao.StudentDao.selectById",6);
        return student;
    }
   }

(2)第二种使用方式,只配置Java Mapper文件的位置,而不需要配置mapper.xml文件的位置,但是第二种方式也需要mapper.xml,那mapper.xml应该放哪呢?

@Transactional
@Service
public class MybatisStudentService {

    @Autowired
    SqlSessionFactory sqlSessionFactory;

    /**
     * 使用Java dao方式,先获取dao代理对象
     * @param id
     * @return
     */
    public Student selectAllByJavaMapper(int id){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //其实看这里是通过java Mapper文件找的方法,那到底怎么和Mapper.xml关联起来呢?
        StudentHaveJavaMapper studentMapper = sqlSession.getMapper(StudentHaveJavaMapper.class);
        Student students = studentMapper.selectById(1);
        return students;
    }
}

StudentHaveJavaMapper.java

package com.xiaolong.dao;

import com.xiaolong.dto.Student;

import java.util.List;

public interface StudentHaveJavaMapper {

    public List<Student> selectAll();

    Student selectById(int id);
}

在这里插入图片描述

<?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.xiaolong.dao.StudentHaveJavaMapper">
    <select id="selectAll"  resultType="com.xiaolong.dto.Student">
        select * from t_student
    </select>

    <select id="selectById" parameterType="int" resultType="com.xiaolong.dto.Student">
        select * from t_student where id = #{id}
    </select>
</mapper>

这里是把Mapper.xml放到了和Java文件相同的位置,而且必须得放到这里,且名称必须和Java文件一致了,原因是啥呢?
mybatis是如何找到xml文件的呢?我们从 上面使用的这行代码看看:
sqlSessionFactory.getConfiguration().addMappers(“com.xiaolong.dao”);

sqlSessionFactory.getConfiguration()是获取了Configuration对象,然后看addMappers()方法
Configuration.java

public void addMappers(String packageName) {
    mapperRegistry.addMappers(packageName);
  }

MapperRegistry.java

public void addMappers(String packageName) {
    addMappers(packageName, Object.class);
  }
  
public void addMappers(String packageName, Class<?> superType) {
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
    //这里通过packageName去找到所有的JAVA Mapper文件
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
    //循环每个java Mapper文件去加载mapper.xml
    for (Class<?> mapperClass : mapperSet) {
      addMapper(mapperClass);
    }
  }

public <T> void addMapper(Class<T> type) {
    if (type.isInterface()) {
      if (hasMapper(type)) {
        throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
      }
      boolean loadCompleted = false;
      try {
        knownMappers.put(type, new MapperProxyFactory<>(type));
        // It's important that the type is added before the parser is run
        // otherwise the binding may automatically be attempted by the
        // mapper parser. If the type is already known, it won't try.
        //这里的type就是Java Mapper文件,比如我们例子里的StudentHaveJavaMapper.java
        MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
        parser.parse();
        loadCompleted = true;
      } finally {
        if (!loadCompleted) {
          knownMappers.remove(type);
        }
      }
    }
  }

MapperAnnotationBuilder.java

public void parse() {
    String resource = type.toString();
    if (!configuration.isResourceLoaded(resource)) {
    //在这里去找xml文件
      loadXmlResource();
      configuration.addLoadedResource(resource);
      assistant.setCurrentNamespace(type.getName());
      parseCache();
      parseCacheRef();
      Method[] methods = type.getMethods();
      for (Method method : methods) {
        try {
          // issue #237
          if (!method.isBridge()) {
            parseStatement(method);
          }
        } catch (IncompleteElementException e) {
          configuration.addIncompleteMethod(new MethodResolver(this, method));
        }
      }
    }
    parsePendingMethods();
  }
private void loadXmlResource() {
    // Spring may not know the real resource name so we check a flag
    // to prevent loading again a resource twice
    // this flag is set at XMLMapperBuilder#bindMapperForNamespace
    if (!configuration.isResourceLoaded("namespace:" + type.getName())) {
    //在这里通过获取Java Mapper类的名称,比如com.xiaolong.dao.StudentHaveJavaMapper.java
      String xmlResource = type.getName().replace('.', '/') + ".xml";
      // #1347
      InputStream inputStream = type.getResourceAsStream("/" + xmlResource);
      if (inputStream == null) {
        // Search XML mapper that is not in the module but in the classpath.
        try {
          inputStream = Resources.getResourceAsStream(type.getClassLoader(), xmlResource);
        } catch (IOException e2) {
          // ignore, resource is not required
        }
      }
      if (inputStream != null) {
        XMLMapperBuilder xmlParser = new XMLMapperBuilder(inputStream, assistant.getConfiguration(), xmlResource, configuration.getSqlFragments(), type.getName());
        xmlParser.parse();
      }
    }
  }

在上方通过获取Java Mapper类的名称,比如com.xiaolong.dao.StudentHaveJavaMapper.java,然后替换成
com/xiaolong/dao/StudentHaveJavaMapper.xml,然后通过Resources.getResourceAsStream(type.getClassLoader(), xmlResource);去加载xml,然后在解析,这就是为啥第二种方式的xml文件必须和Java Mapper类放一起,且名称必须一致了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值