网站制作公司违法,股权设计方案模板,安徽省住房和城乡建设厅官网证件查询,wordpress信息填写SqlSession以及Spring与MyBatis整合
准备所需要的JAR包
要实现MyBatis与Spring的整合#xff0c;很明显需要这两个框架的JAR包#xff0c;但是只是使用这两个框架中所提供的JAR包是不够的#xff0c;还需要配合其他包使用#xff1a;
Spring的JAR包MyBatis的JAR包Spring…SqlSession以及Spring与MyBatis整合
准备所需要的JAR包
要实现MyBatis与Spring的整合很明显需要这两个框架的JAR包但是只是使用这两个框架中所提供的JAR包是不够的还需要配合其他包使用
Spring的JAR包MyBatis的JAR包Spring与MyBatis整合中间包mybatis-spring-x.x.x.jar数据库驱动JAR(以MYSQL为例)mysql-connector-java-x.x.x-bin.jar数据源所需的JAR(DBCP)commons-dbcp2-x.x.x.jar和commons-pool2-x.x.x.jar
配置文件介绍
关于resources文件夹
我们在之前的项目中几乎每次都会创建这个文件夹然后Use as a source folder那么这个文件夹到底是用来干啥的凭什么使用它里面的文件是直接写文件名
实际上这个文件夹是专门存放你的应用所需资源的如XML等配置文件。这个文件夹被标记为source folder后在编译后里面的文件会放到与编译好的文件相同目录里所以你读取的直接使用文件名实际上是相对路径。
pom.xml
如果我们创建的是一个Maven项目就可以在pom.xml里添加properties/properties标签来定义库版本然后在下方的dependencies/dependencies中的dependency/dependency的version/version以${...}形式引用它。
下面的XML文件省略了很多仅为了演示。
propertiesproject.build.sourceEncodingUTF-8/project.build.sourceEncodingjunit.version4.12/junit.version!-- 此处表示省略 --[...]
/propertiesdependencies!-- JUINT --dependencygroupIdjunit/groupIdartifactIdjunit/artifactId!-- 引用上方标签的版本号 --version${junit.version}/versionscopetest/scope/dependency!-- 此处表示省略 --[...]
/dependenciesdb.properties
db.properties主要包含一些数据库连接信息比如JDBC连接驱动、数据库账户名和密码等。
我们在之前的项目中就已经使用过这个文件了但我们一直没有详细介绍过其每条内容的含义实际上语义很明显
jdbc.drivercom.mysql.jdbc.Driver
jdbc.urljdbc:mysql://localhost:3306/db_mybatis?useUnicodetruecharacterEncodingutf8
jdbc.usernamedb_mybatis
jdbc.passworddb_mybatis首先第一行jdbc.driver是指定数据库连接驱动。JDBC即Java数据库连接它定义了一套关系型数据库的规则没错实际上就是接口然后实现并不是由Java官方进行的而是交给各个数据库厂商来做它们打包的库也就是JAR包就被叫做数据库驱动同时也意味着不同数据库就有不同的驱动实现。
程序设计者无需去关心每个数据库驱动是怎么实现的而是像你把手机充电器插到墙上的插座一样把驱动按照接口给“插”进去。这就是面向接口编程的好处。
你的程序只是一个调用者数据库驱动就像一个代理人你要先告诉这个代理人怎么操作然后让这个代理人去真正操纵数据库怎么操纵你是不关心的只要满足你的操作需求即可。你与这个代理人约定的通用交流方式就是刚才的接口而代理人具体的操纵方式就是驱动的实现。
我们所给的代码中很显然是MySQL的数据库驱动后面的mysql.jdbc.Driver实际上是随你pom.xml添加的包一块引入的。
第二行的是数据库连接URL它实际上是数据库JDBC连接字符串的一部分。它的书写形式应该参考数据库驱动提供方的文档
jdbc说明这是一个JDBC的连接字符串mysql说明连接的数据库为MYSQLlocalhost所在部分一般是数据库的网络地址或域名localhost实际上是一个域名它在你系统的HOST文件中被解析到了127.0.0.1通常是这样不绝对你完全可以修改它这个地址是一个回环地址它实际上表示你机器本身。同理我的MySQL如果在远程服务器192.168.10.2上面这里就不再是localhost而是192.168.10.2或者对应的域名。db_mybatis部分对应数据库名称这个我们在之前创建过。useUnicode这里的值为true表示使用Unicode编码它是国际标准字符集将世界上每一种自然语言每个字符都定义为一个唯一编码满足跨语言需要尤其是包含中文的时候。characterEncoding部分是指定Unicode编码的存储方式。Unicode只是一个符号集但并没有规定怎么存放。这里的存放方式为utf8被定义为将码点编码为1到4个字节byte具体取决于有效二进制位的数量。
类似于useUnicode的参数还有很多比如设置SSL等这里不过多介绍碰到了请参考文档或搜索引擎。
jdbc.username和jdbc.password就很简单了一般是具有权限的数据库用户的用户名和密码。分配一个或多个具有部分权限的用户是好习惯而不是一直用root它权限太大了不安全。
app.xml
app.xml为Spring配置文件名称同样不固定根据你自己来。对于内容的解释请看下方代码的注释
!-- 指定XML版本和编码方式为Unicode UTF-8 --
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:contexthttp://www.springframework.org/schema/contextxmlns:txhttp://www.springframework.org/schema/txxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd!-- 指定需要扫描的包使注解生效 --context:component-scanbase-packagexxx.xxxx.xxx /!--读取db.properties --context:property-placeholder locationclasspath:db.properties/!-- 配置数据源 --bean iddataSource classorg.springframework.jdbc.datasource.DriverManagerDataSource!--数据库驱动 --property namedriverClassName value${jdbc.driver} /!--连接数据库的url --property nameurl value${jdbc.url} /!--连接数据库的用户名 --property nameusername value${jdbc.username} /!--连接数据库的密码 --property namepassword value${jdbc.password} //bean!-- 事务管理器依赖于数据源 --bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource //bean !-- 注册事务管理器驱动开启事务注解 --tx:annotation-driven transaction-managertransactionManager/!-- 配置MyBatis工厂 --bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBeanproperty namedataSource refdataSource /!-- 这里指定了MyBatis配置文件为mybatis-config.xml --property nameconfigLocation valueclasspath:mybatis-config.xml//beanbean classorg.mybatis.spring.mapper.MapperScannerConfigurerproperty namebasePackage valuexx.xxx.xx.mapper /property namesqlSessionFactoryBeanName valuesqlSessionFactory //bean/beansmybatis-config.xml
mybatis-config.xml为MyBatis配置文件当然你可以不写它将它的配置写在Spring配置文件中写法不太一样但不建议这么做当文件内容特别多时不利于维护。
?xml version1.0 encodingUTF-8 ?
!DOCTYPE configuration PUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtd
configurationproperties resourcedb.properties /settings!-- 延迟加载的开关 --setting namelazyLoadingEnabled valuefalse /!-- 设置积极加载true或按需加载false --setting nameaggressiveLazyLoading valuetrue /setting namemapUnderscoreToCamelCase valuetrue /setting namelogImpl valueSTDOUT_LOGGING //settingstypeAliases!-- 对应的dao实体对象 --package namexx.xxx.xx.dao //typeAliases!--2.配置Mapper的位置 --mappersmapper resourcexx/xxx/xx/mapper/CustomerMapper.xml //mappers
/configurationlog4j.properties
日志的配置文件
# Global logging configuration
log4j.rootLoggerERROR, stdout
# MyBatis logging configuration...
log4j.logger.top.cairbin.test5DEBUG
# Console output...
log4j.appender.stdoutorg.apache.log4j.ConsoleAppender
log4j.appender.stdout.layoutorg.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern%5p [%t] - %m%n进程、线程与CPU调度
在开始Spring与MyBatis的整合之前为了了解一些概念我们来讲下进程与线程。
什么是进程进程是对程序过程的抽象。它是OS的动态执行单元在传统OS上既是基本分配单元又是基本执行单元。
举个不太严谨的例子你在Windows下打开一个音乐播放器随之你能在任务管理器中看到这一项而这个正在运行的音乐播放器就是一个进程。
线程实际上算是轻量级的进程但二者还是不太相同不过它们的相同点要多余不同点。它是看起来就像是对计算机创建进程的模拟只不过这个模拟是在进程之中的。
进程内存资源相对来讲较独立而多个线程共享进程的内存资源。
另外我们的CPU调度一般是抢占式的我们在使用计算机的时候看起来没啥感觉但实际上CPU一直在“抽疯”——在多个线程之间进行高速切换这就带来一些问题。
有些操作它不是原子的即可分割为更小的操作当一个活没有干完的时候CPU便去干另一个活。
同时多个线程尝试对同一个变量进行修改的时候顺序可能是乱的。
这些都有可能导致线程不安全。什么是线程不安全指多线程并发执行某个代码的时候产生了逻辑上的错误结果与预期值不同。
当然内存可变性以及Java编译器对指令优化也有可能导致这种情况。
SqlSession
对于MyBatis来讲实际上有三种SqlSession我们来分别讲讲它们的区别和使用场景。
首先看一张图片描述再来描述它们的关系 DefaultSqlSession
DefaultSqlSession类是SqlSession接口的默认实现它通常被使用于执行SQL操作数据库。
//读取配置文件
InputStream inputStream Resources.getResourceAsStream(mybatis-config.xml);// 构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);// 获取SqlSession
SqlSession sqlSession sqlSessionFactory.openSession();try {MyDao myDao sqlSession.selectOne(MyMapper.selectDao, 1);System.out.println(myDao);
} finally {sqlSession.close();
}DefaultSqlSession是一个线程不安全的也就是说它不能是单例。
啥是单例某些组件在整个程序运行时只要一个实例对象多个实例化可能会报错。
DefaultSqlSession即然不能是单例那每次从工厂中获取一个不就行了实际上这会带来额外开销和资源重用。
另外DefaultSqlSession还需要手动调用close()方法这很容易忘记虽然对于C程序员是家常便饭但是聪明的你肯定能用我们所学过的东西来解决这一问题吧——没错就是AOP。
我们既想要单例又要线程安全还想要自动关闭怎么办这就有了SqlSessionManager。
SqlSessionManager
SqlSessionManager使用了JDK动态代理技术我们之前讲过动态生成代理对象sqlSessionProxy并通过SqlSessionInterceptor来对DefaultSqlSession进行增强。
虽然对于SqlSessionManager实际上还是创建非单例的DefaultSqlSession来执行方法但SqlSessionManager可以是单例
那你可能会怼我说多个DefaultSqlSession这不还是会造成额外开销和资源重用吗SqlSessionManager还有另外一种形态它会复用线程本地的DefaultSqlSession
线程不安全是由于多个线程之间共享DefaultSqlSession导致的那我在同线程内“共享”复用我自己的DefaultSqlSession那不就解决线程安全问题了吗。这就大大提高了效率。
治不了洋人还治不了你吗雾
SqlSessionTemplate
SqlSessionTemplate是MyBatis与Spring整合时的线程安全SqlSession。
SqlSessionTemplate实现线程安全的思路与SqlSessionManager相反我既然自己管不了我就让别人管——它交给SqlSessionUtils去获取SqlSession。
但从本质上讲SqlSessionTemplate与SqlSessionManager还是一样的。
SqlSessionUtils会先尝试从事务同步器中获取获取不到再从工厂里要。而事务同步器本身就是一个线程本地变量管理器。
所以SqlSessionTemplate与SqlSessionManager在实现线程安全这一点上殊途同归。
但是二者在自动关闭即自动执行close()方法的时候就有区别了。
SqlSessionTemplate分两种情况
当获取的对象由事务同步管理器返回的时候那关闭是交给Spring的。如果是从工厂里拿的直接调用close()方法。
Spring与MyBatis整合
Spring与MyBatis整合方式分为两种
传统Dao方式Mapper接口方式
传统Dao方式整合
采用传统的Dao方式整合Spring和MyBatis框架可采用mybatis-spring中所提供的SqlSessionTemplate类或者SqlSessionDaoSupport类来实现。
由于这种方式在现在的开发中已经不常用了所以这里仅做演示。
Repository
public class CustomerDaoImpl extends SqlSessionDaoSupport implements ICustomerDao{Autowiredpublic void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory){super.sqlSessionFactory sqlSessionFactory;}public void add(Customer customer){[...]}
}更细化的讲解可参考Spring | 整合MyBatis中SqlSessionTemplate和MapperScannerConfigurer类的使用
Mapper接口方式
传统Dao方式会产生大量重复代码而且需要正确指定映射文件中的id。
为了解决上述问题我们采用Mapper的方式整合开发。
基于MapperFactoryBean的整合
MapperFactoryBean是MyBatis-Spring团队提供的一个用来根据Mapper接口生成Mapper对象的类该类在配置文件中使用时可以配置一下参数
mapperInterface用于指定接口SqlSessionFactory用于指定SqlSessionFactorySqlSessionTemplate用于指定SqlSessionTemplate如果与SqlSessionFactory同时设定则一般情况下只会启用SqlSessionTemplate。
虽然使用Mapper接口编程的方式很简单但是在具体使用的时候还是需要遵循一些规范
Mapper接口的名称和对应的XML映射文件名称必须一致XML映射文件中的namespace与Mapper接口的类路径相同Mapper接口方法名要和XML映射文件中定义的每个执行语句的id相同Mapper接口中的方法的输入参数类型和XML映射文件中的parameterType类型相同Mapper接口方法的输出类型要和XML映射文件的resultType类型相同
基于MapperScannerConfigurer的方式
使用上面的方式会使得配置文件臃肿所以我们在做项目开发的时候一般是使用MapperScannerCongigurer的方式进行扫描。
bean classorg.mybatis.spring.mapper.MapperScannerConfigurerproperty namebasePackage valuetop.cairbin.test6.mapper /property namesqlSessionFactoryBeanName valuesqlSessionFactory /
/bean我们新建一个项目top.cairbin.test6至于哪些细节该注意你应当非常清楚了这里就不多说了如果不会请回去看之前的教程。
对于配置文件我们也说的很清楚了接下来直接给文件
pom.xml文件
project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdtop.cairbin/groupIdartifactIdtest6/artifactIdversion0.0.1-SNAPSHOT/versionpackagingjar/packagingnametest6/nameurlhttp://maven.apache.org/urlpropertiesproject.build.sourceEncodingUTF-8/project.build.sourceEncodingmaven.compiler.source1.7/maven.compiler.sourcemaven.compiler.target1.7/maven.compiler.targetjunit.version4.12/junit.versionspring.version5.2.5.RELEASE/spring.versionmybatis.version3.5.4/mybatis.versionmybatis.spring.version2.0.4/mybatis.spring.versionmysql.version8.0.33/mysql.versioncommons-dbcp.version2.7.0/commons-dbcp.version/propertiesdependenciesdependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion${junit.version}/versionscopetest/scope/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion${spring.version}/version/dependency dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion${spring.version}/version/dependencydependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion${mybatis.version}/version/dependencydependencygroupIdorg.mybatis/groupIdartifactIdmybatis-spring/artifactIdversion${mybatis.spring.version}/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion${mysql.version}/version/dependencydependencygroupIdorg.apache.commons/groupIdartifactIdcommons-dbcp2/artifactIdversion${commons-dbcp.version}/version/dependencydependencygroupIdorg.mybatis.generator/groupIdartifactIdmybatis-generator-core/artifactIdversion1.4.0/version/dependency /dependencies
/projectdb.properties文件
jdbc.drivercom.mysql.jdbc.Driver
jdbc.urljdbc:mysql://localhost:3306/db_mybatis?useUnicodetruecharacterEncodingutf8
jdbc.usernamedb_mybatis
jdbc.passworddb_mybatisSpring配置文件app.xml
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xmlns:contexthttp://www.springframework.org/schema/contextxmlns:txhttp://www.springframework.org/schema/txxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd!-- 指定需要扫描的包使注解生效 --context:component-scanbase-packagetop.cairbin.test6 /!--读取db.properties --context:property-placeholder locationdb.properties/!-- 配置数据源 --bean iddataSource classorg.springframework.jdbc.datasource.DriverManagerDataSource!--数据库驱动 --property namedriverClassName value${jdbc.driver} /!--连接数据库的url --property nameurl value${jdbc.url} /!--连接数据库的用户名 --property nameusername value${jdbc.username} /!--连接数据库的密码 --property namepassword value${jdbc.password} //bean!-- 事务管理器依赖于数据源 --bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource //bean !-- 注册事务管理器驱动 --tx:annotation-driven transaction-managertransactionManager/bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBeanproperty namedataSource refdataSource /property nameconfigLocation valuemybatis-config.xml//beanbean classorg.mybatis.spring.mapper.MapperScannerConfigurerproperty namebasePackage valuetop.cairbin.test6.mapper /property namesqlSessionFactoryBeanName valuesqlSessionFactory //bean
/beansmybatis-config.xml文件
?xml version1.0 encodingUTF-8 ?
!DOCTYPE configuration PUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtd
configurationproperties resourcedb.properties /settings!-- 延迟加载的开关 --setting namelazyLoadingEnabled valuefalse /!-- 设置积极加载true或按需加载false --setting nameaggressiveLazyLoading valuetrue /setting namemapUnderscoreToCamelCase valuetrue /setting namelogImpl valueSTDOUT_LOGGING //settingstypeAliasespackage nametop.cairbin.test6.dao //typeAliases!--2.配置Mapper的位置 --mappersmapper resourcetop/cairbin/test6/mapper/CustomerMapper.xml //mappers
/configurationtop.cairbin.test6.dao.Customer类
package top.cairbin.test6.dao;public class Customer {private Integer id; // 主键idprivate String username; // 客户名称private String jobs; // 职业private String phone; // 电话public Integer getId() {return this.id;}public void setId(Integer id) {this.id id;}public String getUsername() {return this.username;}public void setUsername(String username) {this.username username;}public String getJobs() {return this.jobs;}public void setJobs(String jobs) {this.jobs jobs;}public String getPhone() {return this.phone;}public void setPhone(String phone) {this.phone phone;}Overridepublic String toString() {return Customer [id id , username username , jobs jobs , phone phone ];}
}
top.cairbin.test6.mapper下的CustomerMapper.xml
?xml version1.0 encodingUTF-8?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacetop.cairbin.test6.mapper.CustomerMapperresultMap idBaseResultMap typetop.cairbin.test6.dao.Customerid columnid jdbcTypeINTEGER propertyid /result columnusername jdbcTypeVARCHAR propertyusername /result columnjobs jdbcTypeVARCHAR propertyjobs /result columnphone jdbcTypeVARCHAR propertyphone //resultMapsql idBase_Column_Listid, username, jobs, phone/sqlselect idselectByPrimaryKey parameterTypejava.lang.Integer resultMapBaseResultMapselect include refidBase_Column_List /from customerwhere id #{id,jdbcTypeINTEGER}/select
/mapper对应接口top.cairbin.test6.mapper.CustomerMapper
package top.cairbin.test6.mapper;import top.cairbin.test6.dao.Customer;public interface CustomerMapper{// 通过id查询客户Customer selectByPrimaryKey(Integer id);
}我们接下来实现Service层
创建src/main/java下的包top.cairbin.test6.service
然后在包中创建接口ICustomerService
package top.cairbin.test6.service;import top.cairbin.test6.dao.Customer;public interface ICustomerService { public Customer getCustomerByID(int id);
}创建实现这个接口的类CustomerServiceImpl
package top.cairbin.test6.service;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.cairbin.test6.dao.Customer;
import top.cairbin.test6.mapper.CustomerMapper;Service
public class CustomerServiceImpl implements ICustomerService{Autowiredprivate CustomerMapper customerMapper;public Customer getCustomerByID(int id) {Customer customer customerMapper.selectByPrimaryKey(id);return customer;}
}在测试目录src/test/java下的top.cairbin.test6包创建测试类CustomerTest
package top.cairbin.test6;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import top.cairbin.test6.dao.Customer;
import top.cairbin.test6.service.ICustomerService;RunWith(SpringJUnit4ClassRunner.class)
ContextConfiguration(locations { classpath:app.xml })
public class CustomerTest {Autowiredprivate ICustomerService customerService; Testpublic void findTest() {Customer customer customerService.getCustomerByID(1);System.out.println(customer);}
}运行测试得到结果