这里写目录标题
一级目录
二级目录
三级目录
一Spring整合 Mybitis(配置文件版)
首先数据库中存在以下一张需要被操作和被业务持久化的表
:
CREATE TABLE `EnUser` (
`id` int(11) NOT NULL,
`account` bigint(12) DEFAULT NULL,
`password` varchar(20) NOT NULL DEFAULT '',
`brithday` varchar(25) DEFAULT NULL,
`mail` varchar(20) DEFAULT NULL,
`sex` int(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
1创建maven项目,添加依赖
(ioc,aop,mysql,mybitis,数据源druid,springmybitis插件,分页插件,编译环境插件)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SpringMybitis</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1,8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- spring4.3.2 -->
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!-- spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!-- spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!--使用AspectJ方式注解需要相应的包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11</version>
</dependency>
<!--使用AspectJ方式注解需要相应的包 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.11</version>
</dependency>
<!-- mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--数据源druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.3</version>
</dependency>
<!--mybitis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--spring事务-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!--springJDBC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<!--mybitis-spring插件包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
</dependencies>
</project>
2创建实体类
public class EnUser {
private int id;
private int account;
private String password;
private String brithday;
private String mail;
private int sex;
public EnUser(){
super();
}
public EnUser(int id, int account, String password, String brithday, String mail, int sex) {
this.id = id;
this.account = account;
this.password = password;
this.brithday = brithday;
this.mail = mail;
this.sex = sex;
}
@Override
public String toString() {
return "EnUser{" +
"id=" + id +
", account=" + account +
", password='" + password + '\'' +
", brithday=" + brithday +
", mail='" + mail + '\'' +
", sex=" + sex +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getBrithday() {
return brithday;
}
public void setBrithday(String brithday) {
this.brithday = brithday;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getAccount() {
return account;
}
public void setAccount(int account) {
this.account = account;
}
}
3在映射文件mapper/enuser.xml中写映射SQL
例如对数据库表的插入操作:
<!--insertbyparameter-->
<insert id="insert" parameterType="baobaobaobao.entity.EnUser">
insert into EnUser values(#{id},#{account},#{password},#{brithday},#{mail},#{sex})
</insert>
4根据映射SQL创建dao层接口
小知识:持久层=dao层+数据库
一定注意:
Mapper.xml文件中的namespace与mapper接口的类路径相同。
Mapper接口方法名和Mapper.xml中定义的每个statement的id相同。
Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同。
Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同。
package baobaobaobao.dao;
import baobaobaobao.entity.EnUser;
/**
* Created by @author LiuChunhang on 2020/4/6.
*/
public interface EnuserDaoo {
public int insertone(EnUser enuser);
}
5创建数据库属性文件dbConfig.properties
jdbc.url=jdbc:mysql://ip:3306/数据库
jdbc.driver=com.mysql.jdbc.Driver
jdbc.name=用户名
jdbc.password=密码
6创建mybitis配置文件(不包含数据库配置)
<?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>
<!--不用再写属性文件的加载,不用mapper文件的加载,不用配置数据库的连接环境-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="reasonable" value="true"/>
</plugin>
</plugins>
</configuration>
7创建service业务层接口
package baobaobaobao.service;
import baobaobaobao.entity.EnUser;
/**
* Created by @author LiuChunhang on 2020/4/6.
*/
public interface InsertOneFace {
/*建立一个名为是否插入成功的业务,true为成功,否则为失败*/
Boolean insertone1(EnUser enUser);
}
8创建service业务层实现类
package baobaobaobao.service;
import baobaobaobao.dao.EnuserDaoo;
import baobaobaobao.entity.EnUser;
/**
* Created by @author LiuChunhang on 2020/4/6.
*/
public class InsertOne implements InsertOneFace {
public EnuserDaoo enuserDao;
public EnuserDaoo getEnuserDao() {
return enuserDao;
}
public void setEnuserDao(EnuserDaoo enuserDao) {
this.enuserDao = enuserDao;
}
public Boolean insertone1(EnUser enUser) {
int i = enuserDao.insertone(enUser);
if (i>0){
System.out.println("插入成功");
return true;
}else {
System.out.println("插入失败");
return false;
}
}
}
9spring配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--bean管理-->
<!--加载数据库连接属性文件-->
<context:property-placeholder location="classpath:dbConfig.properties"></context:property-placeholder>
<!-- 创建数据源 init-method/destroy-method -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 配置数据库连接基本信息 -->
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.name}"/>
<property name="password" value="${jdbc.password}"/>
<!-- ******配置数据库连接池相关信息******* -->
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="5"/>
<property name="minIdle" value="2"/>
<property name="maxActive" value="10"/>
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="10000"/>
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000"/>
<property name="testWhileIdle" value="true"/>
<!-- 这里建议配置为TRUE,防止取到的连接不可用 -->
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="false"/>
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="true"/>
<property name="maxPoolPreparedStatementPerConnectionSize"
value="20"/>
<!-- 这里配置提交方式,默认就是TRUE,可以不用配置 -->
<property name="defaultAutoCommit" value="true"/>
<!-- 验证连接有效与否的SQL,不同的数据配置不同 -->
<property name="validationQuery" value="select 1"/>
</bean>
<!--配置SqlSessionFactoryBean-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatisConfig.xml"></property>
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
</bean>
<!--因为接口无法直接被NEW出来,所以需要借用插件来扫描管理接口-->
<bean id="configurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="baobaobaobao.dao"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
<!--Service-->
<bean id="insertOne" class="baobaobaobao.service.InsertOne">
<!--引入dao层依赖,如果接口已经被ioc容器管理,ref属性按照规则应填写接口名首字母小写-->
<property name="enuserDao" ref="enuserDaoo"></property>
</bean>
<!-- 事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务切入点 -->
<aop:config>
<aop:advisor advice-ref="advice" pointcut="execution(* baobaobaobao.service.InsertOne.*(..))" />
</aop:config>
<!-- 配置事务的属性 -->
<tx:advice id="advice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="ins*" isolation="READ_COMMITTED" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
</beans>
10测试
package baobaobaobao;
import baobaobaobao.entity.EnUser;
import baobaobaobao.service.InsertOneFace;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
/**
* Created by @author LiuChunhang on 2020/4/6.
*/
public class Test {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext Context = new ClassPathXmlApplicationContext("applicationContext.xml");
EnUser enuser = new EnUser(15,222222,"333333","1998-11-11","222222",1);
InsertOneFace insertOne = Context.getBean(InsertOneFace.class);
Boolean aBoolean = insertOne.insertone1(enuser);
}
}
二Spring整合 Mybitis(使用注解)
与一Spring整合 Mybitis(配置文件版)前1,2,3,4,5,6,7个步骤相同,
第 8步创建service业务层实现类有以下变化(加注解)
package baobaobaobao.service;
import baobaobaobao.dao.EnuserDaoo;
import baobaobaobao.entity.EnUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* Created by @author LiuChunhang on 2020/4/6.
*/
@Service
public class InsertOne implements InsertOneFace {
@Autowired
public EnuserDaoo enuserDao;
public EnuserDaoo getEnuserDao() {
return enuserDao;
}
public void setEnuserDao(EnuserDaoo enuserDao) {
this.enuserDao = enuserDao;
}
@Transactional
public Boolean insertone1 (EnUser enUser) {
if (enuserDao.insertone(enUser)>0){
System.out.println("插入成功");
return true;
}else {
System.out.println("插入失败");
return false;
}
}
}
第9步的spring的配置文件applicationContext.xml有以下变化
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--bean管理-->
<!--加载数据库连接属性文件-->
<context:property-placeholder location="classpath:dbConfig.properties"></context:property-placeholder>
<!--启用classpath-->
<context:component-scan base-package="baobaobaobao"></context:component-scan>
<!--启用事务注解-->
<tx:annotation-driven transaction-manager="txManager"></tx:annotation-driven>
<!-- 事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置SqlSessionFactoryBean-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatisConfig.xml"></property>
<property name="mapperLocations" value="classpath:mapper/EnUser.xml"></property>
</bean>
<!--因为接口无法直接被NEW出来,所以需要借用插件来扫描管理接口-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="baobaobaobao.dao"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
<!-- 创建数据源 init-method/destroy-method -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 配置数据库连接基本信息 -->
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.name}"/>
<property name="password" value="${jdbc.password}"/>
<!-- ******配置数据库连接池相关信息******* -->
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="5"/>
<property name="minIdle" value="2"/>
<property name="maxActive" value="10"/>
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="10000"/>
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000"/>
<property name="testWhileIdle" value="true"/>
<!-- 这里建议配置为TRUE,防止取到的连接不可用 -->
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="false"/>
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="true"/>
<property name="maxPoolPreparedStatementPerConnectionSize"
value="20"/>
<!-- 这里配置提交方式,默认就是TRUE,可以不用配置 -->
<property name="defaultAutoCommit" value="true"/>
<!-- 验证连接有效与否的SQL,不同的数据配置不同 -->
<property name="validationQuery" value="select 1"/>
</bean>
</beans>
第十步测试相同
三思考:为什么dao层和service层要用接口思想?
DAO接口
为每个DAO声明接口的好处在于:
可以在尚未实现具体DAO的时候编写上层代码,如Service里对DAO的调用
可以为DAO进行多实现,例如有JDBCDAO实现,MyBatisDAO实现,而不需要更改上层代码,只需要简单的在Spring的IoC配置里修改一下注入的DAO实现
Service接口
可以在尚未实现具体Service情况下编写上层改代码,如Controller对Service的调用
Spring无论是AOP还是事务管理的实现都是基于动态代理的,而动态代理的实现依赖于接口,所以必须有接口的定义才能使用这些功能
可以对Service进行多实现
总的来说,接口的优势就在于规范方法参数,返回值,另外可以实现多态,结合Spring来说接口对于使用Spring的各种功能也是不可或缺的
另外,使用接口对于测试代码也是有好处的,对于mock一个方法来说,我们不需要关注方法的具体实现,因为本来mock就会将方法内部实现置空,我们的关注点集中于方法参数以及返回值,所以使用接口对于快速实现流程上的测试是有好处的.
使用接口是为了调用与实现解耦,带来的好处是可以各干各的了,带来的坏处是从一个概念变成了两个概念,增加了系统的复杂度。衡量一下在具体场景中是弊大于利还是利大于弊,就可以做选择了。
四请注意,如果使用了接口,在用ioc创建对象的时候,例如 Context.getBean(InsertOneFace.class);
由于java多态特征,里面填写的类名必须为为接口的类名.否则会报异常( No qualifying bean of type [service.InsertOne] is defined)!
异常如下:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [baobaobaobao.service.InsertOne] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:374)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:334)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1088)
at baobaobaobao.Test.main(Test.java:19)