SpringBoot 集成 Mybatis

SpringBoot 集成 Mybatis

Springboot 2.0选择HikariCP作为默认数据库连接池(相比c3p0,HikariCP拥有更快的速度,更少的代码量【意味着执行效率越高、发生bug的可能性越低】,更高的稳定性和可靠性,和druid相比,侧重点略有不同,HikariCP可能有更优秀的速度),我们在项目中添加了cglib动态代理依赖,添加了连接池的配置信息:
在这里插入图片描述

1、添加mybatis依赖:

   <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>x.x.x</version>
    </dependency>
   
springboot:
     <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.3.2</version>
     </dependency>

2、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>
	<settings>
		<!--全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存。默认:true-->
		<setting name="cacheEnabled" value="true"/>

		<!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。默认false-->
		<setting name="lazyLoadingEnabled" value="true"/>

		<!--当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载(参考lazyLoadTriggerMethods)。3.4.1后默认false,之前默认true-->
		<setting name="aggressiveLazyLoading" value="false"/>

		<!--是否允许单一语句返回多结果集(需要兼容驱动)。默认true-->
		<setting name="multipleResultSetsEnabled" value="true"/>

		<!--使用列标签代替列名。默认true-->
		<setting name="useColumnLabel" value="true"/>

		<!--允许 JDBC 支持自动生成主键,需要驱动兼容。 如果设置为 true 则这个设置强制使用自动生成主键,
			尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。默认false-->
		<setting name="useGeneratedKeys" value="false"/>

		<!--指定 MyBatis 应如何自动映射列到字段或属性。
		NONE:表示取消自动映射;
		PARTIAL:只会自动映射没有定义嵌套结果集映射的结果集。
		FULL:会自动映射任意复杂的结果集(无论是否嵌套)。
		默认PARTIAL-->
		<setting name="autoMappingBehavior" value="PARTIAL"/>

		<!--配置默认的执行器。
		SIMPLE 就是普通的执行器;
		REUSE 执行器会重用预处理语句(prepared statements);
		BATCH 执行器将重用语句并执行批量更新。
		默认SIMPLE-->
		<setting name="defaultExecutorType" value="SIMPLE"/>

		<!--设置超时时间,它决定驱动等待数据库响应的秒数。-->
		<setting name="defaultStatementTimeout" value="25"/>

		<!--允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为false。-->
		<setting name="safeRowBoundsEnabled" value="false"/>

		<!--是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。-->
		<setting name="mapUnderscoreToCamelCase" value="false"/>

		<!--MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。
		默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。
		若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。-->
		<setting name="localCacheScope" value="SESSION"/>

		<!--当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。
		某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。默认OTHER-->
		<setting name="jdbcTypeForNull" value="OTHER"/>

		<!--指定哪个对象的方法触发一次延迟加载。默认equals,clone,hashCode,toString-->
		<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>

		<!--指定动态 SQL 生成的默认语言。-->
		<setting name="defaultScriptingLanguage" value="xml"/>

		<!--指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,
		这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。
		注意基本类型(int、boolean等)是不能设置成 null 的。
		默认false-->
		<setting name="callSettersOnNulls" value="false"/>

		<!--指定 MyBatis 增加到日志名称的前缀。-->
		<setting name="logPrefix" value="employees"/>

		<!--指定 MyBatis 所用日志的具体实现,未指定时将自动查找。
		SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING-->
		<setting name="logImpl" value="STDOUT_LOGGING" />

		<!--指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。CGLIB | JAVASSIST-->
		<setting name="proxyFactory" value="CGLIB"/>
	</settings>

</configuration>

3、构建 SqlSessionFactory:

SqlSessionFactory包含了对 MyBatis 系统的核心设置,包含获取数据库连接实例的数据源(DataSource)和决定事务作用域和控制方式的事务管理器(TransactionManager)

(1)使用XML构建 SqlSessionFactory:

String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

mybatis-config.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="org/mybatis/example/BlogMapper.xml"/>
      </mappers>
    </configuration>

(2)不使用 XML 构建 SqlSessionFactory:

DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);

(3)个人采用非xml的形式,写了一个MybatisConfig 的配置类:

@Configuration
@EnableConfigurationProperties(BaseDataSourceConfig.class)
@MapperScan(basePackages = {"com.wj.spc.demo_1203.mysql.dao"}, sqlSessionTemplateRef = "sqlSessionTemplate")
public class MybatisConfig {

    @Autowired
    private BaseDataSourceConfig baseDataSourceConfig;

    @Value("${spring.datasource.url}")
    private String jdbcUrl;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${spring.datasource.username}")
    private String username;

    @Bean(name = "dataSource")
    @Primary
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();

        config.setJdbcUrl(jdbcUrl);
        config.setUsername(username);
        config.setPassword(password);
        config.setReadOnly(baseDataSourceConfig.isReadOnly());
        config.setConnectionTimeout(baseDataSourceConfig.getConnectionTimeout());
        config.setIdleTimeout(baseDataSourceConfig.getIdleTimeout());
        config.setMaxLifetime(baseDataSourceConfig.getMaxLifetime());
        config.setMaximumPoolSize(baseDataSourceConfig.getMaximumPoolSize());
        config.setMinimumIdle(baseDataSourceConfig.getMinimumIdle());
        config.setAutoCommit(baseDataSourceConfig.isAutoCommit());
        config.setConnectionTestQuery(baseDataSourceConfig.getConnectionTestQuery());

        return new HikariDataSource(config);

    }

    @Bean(name = "sqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mappers/*.xml"));

        return sessionFactory.getObject();
    }

    @Bean(name = "sqlSessionTemplate")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

TransactionManagementConfig :

@Configuration
public class TransactionManagementConfig implements TransactionManagementConfigurer {

    @Resource(name = "myTransactionManager")
    private PlatformTransactionManager annotationTransactionManager;

    @Bean(name = "myTransactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return annotationTransactionManager;
    }
}

4、从 SqlSessionFactory 中获取 SqlSession:

SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。例如:

SqlSession session = sqlSessionFactory.openSession();
try {
  BMapper mapper = session.getMapper(BMapper.class);
  B b= mapper.selectB(1);
} finally {
  session.close();
}

5、作用域和生命周期

(1)SqlSessionFactory:
a、SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。
b、使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏味道(bad smell)”。
c、因此 SqlSessionFactory 的最佳作用域是应用作用域。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

(2)SqlSession:
a、每个线程都应该有它自己的 SqlSession 实例。
b、SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
c、绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。也绝不能将 SqlSession 实例的引用放在任何类型的管理作用域中,比如 Servlet 架构中的 HttpSession。如果你现在正在使用一种 Web 框架,要考虑 SqlSession 放在一个和 HTTP 请求对象相似的作用域中。换句话说,每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它。这个关闭操作是很重要的,你应该把这个关闭操作放到 finally 块中以确保每次都能执行关闭。

(3)映射器实例(Mapper Instances 接收映射的mapper接口)
a、映射器是一个你创建来绑定你映射的语句的接口。
b、映射器接口的实例是从 SqlSession 中获得的。
c、虽然理论上映射器实例的作用域了应该等同于sqlSession,但是映射器实例的最佳作用域是方法作用域,即:映射器实例应该在调用它们的方法中被请求,用过之后即可废弃,并不需要显式地关闭映射器实例:

SqlSession session = sqlSessionFactory.openSession();
try {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  // do work
} finally {
  session.close();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值