两个月前跟着b站动力节点王鹤老师的Spring框架教程视频学习完了Spring框架,在学习过程中我将视频中涉及的代码都一行一行手敲了一遍,并且把Spring入门相关的资料整理了一下,在这里记录一下我在Spring框架学习过程中的笔记和一些心得,希望能帮助到想要通过文字教程入门Spring这一框架的小伙伴哦!
视频地址:2020最新Spring框架教程【IDEA版】-Spring框架从入门到精通
文章目录
整合 Spring 和 MyBatis
1. 概述与回顾
Spring 像插线板一样,mybatis 框架是插头,可以容易的组合到一起。插线板 spring 插上 mybatis,两个框架就是一个整体。把 mybatis 框架和 spring 框架集成在一起,像一个框架一样使用。
-
如何整合?
使用的技术是:ioc 。
-
为什么 ioc 能把 mybatis 和 spring 集成在一起,像一个框架?
因为 ioc 能创建对象。可以把 mybatis 框架中的对象交给 spring 统一创建, 而开发人员从 spring 中获取对象。开发人员就不用同时面对两个或多个框架了, 只需要面对一个 spring 框架进行开发。
-
mybatis 使用步骤?
1.定义 dao 接口 :StudentDao
2.定义 mapper 文件 :StudentDao.xml
3.定义 mybatis 的主配置文件 :mybatis.xml
4.创建 dao 的代理对象 :StudentDao dao = SqlSession.getMapper(StudentDao.class);List<Student> students = dao.selectStudents();
-
要使用 dao 对象,需要使用 getMapper() 方法,怎样才能使用 getMapper() 方法,需要哪些条件?
1.获取 SqlSession 对象, 需要使用 SqlSessionFactory 的 openSession() 方法。
2.创建 SqlSessionFactory 对象。 通过读取 mybatis 的主配置文件,用 SqlSessionFactoryBuilder 的 build() 方法能创建 SqlSessionFactory 对象
需要 SqlSessionFactory 对象, 使用 Factory 能获取 SqlSession,有了 SqlSession 就能有 dao ,而目的就是使用 dao 对象来调用 crud 方法。
Factory 对象的创建需要读取主配置文件
主配置文件:
- 数据库信息
<environment id="mydev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<!--数据库的驱动类名-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!--连接数据库的url字符串-->
<property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
<!--访问数据库的用户名-->
<property name="username" value="root"/>
<!--密码-->
<property name="password" value="123456"/>
</dataSource>
- mapper文件的位置
<mappers>
<mapper resource="com/kaho/dao/StudentDao.xml"/>
<!--<mapper resource="com/kaho/dao/SchoolDao.xml" />-->
</mappers>
实际开发中,我们会使用独立的连接池类替换 mybatis 默认自带的 POOLED, 把连接池类也交给spring创建。
通过以上的说明,我们需要让 spring 创建以下对象:
1.独立的连接池类的对象, 使用阿里的 druid 连接池
2.SqlSessionFactory 对象
3.创建出 dao 对象
需要学习就是上面三个对象的创建语法,这里可以使用 xml 的 bean 标签来进行创建。
2. 实现步骤
创建 maven 工程 spring-mybatis,模板使用 quickstart
总目录结构:
2.1 创建数据库表
创建一个数据库:springdb 在其中创建一张表:student
2.2 配置 maven 依赖 pom.xml
<?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>com.kaho</groupId>
<artifactId>ch07-spring-mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<!--junit单元测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--spring核心ioc依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--spring事务相关依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!--mybatis-spring集成的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<!--druid数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
</dependencies>
<build>
<!--目的是把src/main/java目录中的xml文件包含到输出结果中。输出到classes目录中-->
<resources>
<resource>
<directory>src/main/java</directory><!--所在的目录-->
<includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<!--指定jdk版本-->
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.3 定义实体类 Student
在 main.java.com.kaho 下创建一个包 domain,用于存放实体类:Student.java
package com.kaho.domain;
public class Student {
//属性名和列名一样
private Integer id;
private String name;
private String email;
private Integer age;
//无参、有参构造器,get、set方法,toString方法
}
2.4 定义 StudentDao 接口
在 main.java.com.kaho 下创建一个包 dao,用于存放 dao接口:StudentDao.java
package com.kaho.dao;
import com.kaho.domain.Student;
import java.util.List;
public interface StudentDao {
int insertStudent(Student student);//插入学生信息
List<Student> selectStudents();//查询表中所有学生
}
2.5 定义映射文件 mapper.xml
在 Dao 接口的包中创建 MyBatis 的映射文件 mapper.xml,命名与接口名相同,本例为 StudentDao.xml。mapper 中的 namespace 取值也为 Dao 接口的全限定名称。
<?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.kaho.dao.StudentDao">
<insert id="insertStudent">
insert into student values (#{id},#{name},#{email},#{age})
</insert>
<select id="selectStudents" resultType="com.kaho.domain.Student">
select id,name,email,age from student order by id desc /*desc 降序排序*/
</select>
</mapper>
2.6 定义 MyBatis 主配置文件
在 src 下创建 resources 包,定义 MyBatis 的主配置文件,命名为 mybatis.xml
这里有两点需要注意:
(1)主配置文件中不再需要数据源的配置了。因为数据源要交给 Spring 容器来管理了。
(2)这里对 mapper 映射文件的注册,使用 <package/> 标签,即只需给出 mapper 映射文件所在的包即可。因为 mapper 的名称与 Dao 接口名相同,可以使用这种简单注册方式。这种方式的好处是,若有多个映射文件,这里的配置也是不用改变的。当然,也可使用原来的 <resource/> 标签方式。
<?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:控制mybatis全局行为-->
<settings>
<!--设置mybatis输出日志,打印到控制台上-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--设置别名-->
<typeAliases>
<!--name:实体类所在的包名-->
<package name="com.kaho.domain"/>
</typeAliases>
<!-- sql mapper(sql映射文件)的位置 -->
<mappers>
<!--
name : 是包名,这个包中的所有mapper.xml文件一次都能加载
-->
<package name="com.kaho.dao"/>
</mappers>
</configuration>
2.7 定义 Service 接口和实现类
定义 StudentService 接口:
package com.kaho.service;
import com.kaho.domain.Student;
import java.util.List;
public interface StudentService {
int addStudent(Student student);
List<Student> queryStudents();
}
StudentServiceImpl 实现类:
package com.kaho.service.impl;
import com.kaho.dao.StudentDao;
import com.kaho.domain.Student;
import com.kaho.service.StudentService;
import java.util.List;
public class StudentServiceImpl implements StudentService {
//引用类型
private StudentDao studentDao;
//使用set注入来进行赋值,用ref而非value
public void setStudentDao(StudentDao studentDao){
this.studentDao = studentDao;
}
//加入一个学生
@Override
public int addStudent(Student student) {
return studentDao.insertStudent(student);
}
//查询所有学生
@Override
public List<Student> queryStudents() {
return studentDao.selectStudents();
}
}
2.8 修改 Spring 配置文件
(1)数据源的配置
使用 JDBC 模板,首先需要配置好数据源,数据源直接以 Bean 的形式配置在 Spring 配置文件中。
Druid 数据源 DruidDataSource
Druid 是阿里的开源数据库连接池。是 Java 语言中最好的数据库连接池。Druid 能够提供强大的监控和扩展功能。
官网:https://github.com/alibaba/druid
使用地址:https://github.com/alibaba/druid/wiki/ 常见问题
配置连接池:
Spring 配置文件中数据源的配置:
<!--
声明数据源DataSource,作用是连接数据库
无需在此配置驱动,可以根据url检测出驱动
-->
<bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!--set注入给DruidDataSource提供连接数据库的信息-->
<property name="url" value="jdbc:mysql://localhost:3306/springdb?useUnicode=true&characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="123456" />
<property name="maxActive" value="20" /><!--最大连接数-->
</bean>
init-method=“init” 和 destroy-method=“close” 分别是初始化方法和销毁方法,是固定的
(2)使用属性配置文件 properties
为了便于维护,可以将数据库连接信息写入到属性文件中,使 Spring 配置文件从中读取数据。
属性文件名称自定义(一般命名为 jdbc.properties ),将其放在 resources 资源目录下。
jdbc.properties :
jdbc.url=jdbc:mysql://localhost:3306/springdb?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456
jdbc.max=20
- 注意这里是在 properties 文件中,& 需要改回 &
Spring 配置文件中数据源的配置:
<!--
把数据库的配置信息写在一个独立的文件,便于修改数据库的配置内容
需要让spring知道jdbc.properties文件的位置——使用<context:property-placeholder>标签,属性是location ,注意要加上 classpath:
-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!--set注入给DruidDataSource提供连接数据库的信息-->
<!--使用属性配置文件中的数据,语法: ${key} -->
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="${jdbc.max}" /><!--最大连接数-->
</bean>
(3)注册 SqlSessionFactoryBean
<!--声明mybatis中所提供的SqlSessionFactoryBean类,这个类内部会创建SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--set注入,把数据库连接池赋给dataSource属性-->
<property name="dataSource" ref="myDataSource" />
<!--mybatis主配置文件的位置
configLocation属性是Resource类型,用来读取配置文件
使用value来赋值,指定文件的路径,使用classpath:表示文件的位置
-->
<property name="configLocation" value="classpath:mybatis.xml" />
</bean>
(4)定义 Mapper 扫描配置器 MapperScannerConfigurer
Mapper 扫描配置器 MapperScannerConfigurer 会自动生成指定的基本包中 mapper 的代理对象。该 Bean 无需设置 id 属性。basePackage 使用分号或逗号设置多个包。
<!--创建dao对象,使用SqlSession的getMapper(StudentDao.xml)
MapperScannerConfigurer:在内部调用getMapper()生成每个dao接口的代理对象
这个bean无需指定id属性
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定SqlSessionFactory对象的id
sqlSessionFactoryBeanName是String属性,所以这里用value不用ref
-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
<!--指定包名,包名是dao接口所在的包名。
MapperScannerConfigurer会扫描这个包中的所有接口,把每个接口都执行一次getMapper()方法,得到每个接口的dao对象。
创建好的dao对象会放入到spring容器中。dao对象的默认名称是 首字母小写的接口名
-->
<property name="basePackage" value="com.kaho.dao" />
</bean>
2.9 注册 Service 对象并注入 Dao 属性
向 Service 注入 Mapper 代理对象时需要注意,由于通过 Mapper 扫描配置器 MapperScannerConfigurer 生成的 Mapper 代理对象没有名称 id,所以在向 Service 注入 Mapper 代理时,无法通过名称 id 注入。但可通过**接口的简单类名(首字母小写的接口名)**注入,因为生成的是这个 Dao 接口的对象。
<!--注册StudentService对象,给其属性studentDao注入值-->
<bean id="studentService" class="com.kaho.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao" />
</bean>
2.10 Spring 配置文件完整配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
把数据库的配置信息写在一个独立的文件,便于修改数据库的配置内容
需要让spring知道jdbc.properties文件的位置——使用<context:property-placeholder>标签,属性是location
-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--
声明数据源DataSource,作用是连接数据库
无需在此配置驱动,可以根据url检测出驱动
-->
<bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!--set注入给DruidDataSource提供连接数据库的信息-->
<!--使用属性配置文件中的数据,语法: ${key} -->
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="${jdbc.max}" /><!--最大连接数-->
</bean>
<!--声明mybatis中所提供的SqlSessionFactoryBean类,这个类内部会创建SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--set注入,把数据库连接池赋给dataSource属性-->
<property name="dataSource" ref="myDataSource" />
<!--mybatis主配置文件的位置
configLocation属性是Resource类型,用来读取配置文件
使用value来赋值,指定文件的路径,使用classpath:表示文件的位置
-->
<property name="configLocation" value="classpath:mybatis.xml" />
</bean>
<!--创建dao对象,使用SqlSession的getMapper(StudentDao.xml)
MapperScannerConfigurer:在内部调用getMapper()生成每个dao接口的代理对象
sqlSessionFactoryBeanName是String属性,所以用value不用ref
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定SqlSessionFactory对象的id-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
<!--指定包名,包名是dao接口所在的包名。
MapperScannerConfigurer会扫描这个包中的所有接口,把每个接口都执行一次getMapper()方法,得到每个接口的dao对象。
创建好的dao对象会放入到spring容器中。dao对象的默认名称是 首字母小写的接口名
-->
<property name="basePackage" value="com.kaho.dao" />
</bean>
<!--注册StudentService对象,给其属性studentDao注入值-->
<bean id="studentService" class="com.kaho.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao" />
</bean>
</beans>
无注释精简版:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="${jdbc.max}" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="configLocation" value="classpath:mybatis.xml" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
<property name="basePackage" value="com.kaho.dao" />
</bean>
<bean id="studentService" class="com.kaho.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao" />
</bean>
</beans>
2.11 Service 测试
@Test
public void testServiceAdd(){
String config = "applicationContext.xml";
ApplicationContext ctx= new ClassPathXmlApplicationContext(config);
//获取spring容器中的service对象
StudentService service = (StudentService) ctx.getBean("studentService");
Student student = new Student(1009,"杜甫","dufu@qq.com",25);
int nums = service.addStudent(student);
//spring和mybatis整合在一起使用时,事务是自动提交的,无需执行SqlSession.commit();
System.out.println("nums=" + nums);
}
spring和mybatis整合在一起使用时,事务是自动提交的,无需执行SqlSession.commit();
@Test
public void testServiceQuery(){
String config = "applicationContext.xml";
ApplicationContext ctx= new ClassPathXmlApplicationContext(config);
//获取spring容器中的Service对象
StudentService service = (StudentService) ctx.getBean("studentService");
List<Student> students = service.queryStudents();
for (Student stu : students){
System.out.println(stu);
}
}
Student{id=1009, name='杜甫', email='dufu@qq.com', age=25}
Student{id=1008, name='李白', email='libai@qq.com', age=26}
Student{id=1007, name='桐谷和人', email='tonggu@qq.com', age=18}
Student{id=1006, name='关羽', email='guangyu@163.com', age=20}
Student{id=1005, name='盾山', email='dunshan@qq.com', age=null}
Student{id=1004, name='刘备', email='liubei@163.com', age=20}
Student{id=1003, name='张飞', email='zhangfei@163.com', age=20}
Student{id=1002, name='张三', email='zs@sina.com', age=28}
Student{id=1001, name='李四', email='lisi@qq.com', age=20}