02【Spring注解开发、JdbcTemplate、整合Junit】
一、注解配置
相对于XML方式而言,通过注解的方式配置bean更加简洁和优雅,需要注意的是,注解配置和 xml 配置要实现的功能都是一样的,只是配置的形式不一样。
关于实际的开发中到底使用xml还是注解,每家公司有着不同的使用习惯。所以这两种配置方式我们都需要掌握。
1.1 使用xml方式配置增删改查
1.1.1 pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
</dependencies>
1.1.2 实体类:
- sql语句:
drop table if exists user;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `user` VALUES (1, 'admin', '111');
INSERT INTO `user` VALUES (2, 'root', '222');
INSERT INTO `user` VALUES (3, 'zhangsan', '333');
INSERT INTO `user` VALUES (4, 'lisi', '444');
- 实体类:
package com.dfbz.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
}
1.1.3 controller
package com.dfbz.controller;
import com.dfbz.entity.User;
import com.dfbz.service.UserService;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class UserController {
private UserService userService;
public User findById(Integer id){
return userService.findById(id);
}
// 提供set方法
public void setUserService(UserService userService) {
this.userService = userService;
}
}
1.1.4 service
package com.dfbz.service;
import com.dfbz.dao.UserDao;
import com.dfbz.entity.User;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class UserService {
private UserDao userDao;
/**
* 根据id查询用户
* @param id
* @return
*/
public User findById(Integer id) {
return userDao.findById(id);
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
1.1.5 dao
package com.dfbz.dao;
import com.dfbz.entity.User;
import javax.sql.DataSource;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class UserDao {
private DataSource dataSource;
/**
* 根据id查询用户
*
* @param id
* @return
*/
public User findById(Integer id) {
try {
PreparedStatement ps = dataSource.getConnection().prepareStatement("select * from user where id=?");
ps.setInt(1, id);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return new User(rs.getInt("id"), rs.getString("username"), rs.getString("password"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
// 提供set方法
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
1.1.6 配置文件
- jdbc.properties:
jdbc.username=root
jdbc.password=admin
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.driverClassName=com.mysql.jdbc.Driver
- spring.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--加载jdbc.properties配置文件-->
<context:property-placeholder location="jdbc.properties" />
<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="url" value="${jdbc.url}" />
<property name="driverClassName" value="${jdbc.driverClassName}" />
</bean>
<!--配置userDao-->
<bean id="userDao" class="com.dfbz.dao.UserDao">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="userService" class="com.dfbz.service.UserService">
<!--注入userDao-->
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userController" class="com.dfbz.controller.UserController">
<!--注入userService-->
<property name="userService" ref="userService" />
</bean>
</beans>
1.2 常用注解
- 1)普通组件:@Component
往IOC容器中添加一个普通组件;
- 2)dao层组件:@Respository
往IOC容器中添加一个dao层组件;
- 3)service层组件:@Service
往IOC容器中添加一个service层组件;
- 4)controller层组件:@Controller
往IOC容器中添加一个controller组件;
其实Spring第一版注解的实现(spring 2.5),就是使用一个@Component。从3.0以后,作者认为根据分层的需要,把它拆成了四个。为了可以让开发人员,可见即可得,一看到注解,立即知道类的性质。所以分成了四个
注意:@Component、@Respository、@Service、@Controller这几个注解仅仅是为了让开发人员自己明确当前的组件扮演的角色。他们的作用及属性都是一模一样的,他们只不过是提供了更加明确的语义化。
组件命名规则
-
默认情况:使用组件的简单类名首字母小写后得到的字符串作为bean的id
-
使用组件注解的value属性指定bean的id
定义实体类:
package com.dfbz.entity;
import org.springframework.stereotype.Component;
/**
* @author lscl
* @version 1.0
* @intro:
*/
// 定义一个组件类属于spring.xml中的<bean>
@Component
public class Book {
private String id;
private String name;
private String price;
}
1.3 扫描组件
Spring3.0后为我们引入了组件自动扫描机制,它可以在指定包及子包底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,并把这些类纳入进spring容器中管理。它的作用和在xml文件中使用bean节点配置组件是一样的。
- spring.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--
包扫描
base-package:指定要扫码的包
-->
<context:component-scan base-package="com.dfbz" />
</beans>
1.4 组件装配
Controller组件中往往需要用到Service组件的实例,Service组件中往往需要用到Repository组件的实例。Spring可以通过注解的方式帮我们实现属性的装配。
1.4.1 改造xml方式代码
- UserController:
package com.dfbz.controller;
import com.dfbz.entity.User;
import com.dfbz.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@Component("userController") // 注册UserController到IOC容器,id默认为类名首字母小写
public class UserController {
// 装配UserService
@Autowired
private UserService userService;
public User findById(Integer id){
return userService.findById(id);
}
// 不需要提供set方法
}
- UserService:
package com.dfbz.service;
import com.dfbz.dao.UserDao;
import com.dfbz.entity.User;
import org.springframework.stereotype.Service;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@Service
public class UserService {
@Autowired
private UserDao userDao;
/**
* 根据id查询用户
* @param id
* @return
*/
public User findById(Integer id) {
return userDao.findById(id);
}
}
- UserDao:
package com.dfbz.dao;
import com.dfbz.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import javax.sql.DataSource;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@Repository
public class UserDao {
@Autowired
private DataSource dataSource;
/**
* 根据id查询用户
*
* @param id
* @return
*/
public User findById(Integer id) {
try {
PreparedStatement ps = dataSource.getConnection().prepareStatement("select * from user where id=?");
ps.setInt(1, id);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return new User(rs.getInt("id"), rs.getString("username"), rs.getString("password"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
}
- spring.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--
包扫描
base-package:指定要扫描的包(会扫描子包孙包等..)
-->
<context:component-scan base-package="com.dfbz" />
<!--加载jdbc.properties配置文件-->
<context:property-placeholder location="jdbc.properties" />
<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="url" value="${jdbc.url}" />
<property name="driverClassName" value="${jdbc.driverClassName}" />
</bean>
</beans>
1.4.2 @Autowired注解
@Autowired注解:用于根据类型给引用装配容器的对象
构造器、普通字段、一切具有参数的方法都可以应用@Autowired注解
- 在属性上使用:
@Component("userController") // 注册UserController到IOC容器,id默认为类名首字母小写
public class UserController {
// 装配UserService
@Autowired
private UserService userService;
public User findById(Integer id){
return userService.findById(id);
}
}
- 在方法上使用:
@Component("userController") // 注册UserController到IOC容器,id默认为类名首字母小写
public class UserController {
private UserService userService;
/**
* 在方法上标注@Autowired注解
* @param userService
*/
@Autowired
public void setUserService(UserService userService){
this.userService=userService;
}
public User findById(Integer id){
return userService.findById(id);
}
}
- 在构造方法上使用:
@Component("userController") // 注册UserController到IOC容器,id默认为类名首字母小写
public class UserController {
private UserService userService;
@Autowired
public UserController(UserService userService){
this.userService=userService;
}
public User findById(Integer id){
return userService.findById(id);
}
}
Tips:@Autowired注解是根据类型进行匹配的,当IOC容器中存在两个一样的类型时将默认使用首字母小写的名称类型;
1.4.3 @Qualifier注解
@Qualifier注解:用于指定装配的对象名,使用@Autowired装配对象时,@Autowired是根据对象类型来装配的,当容器中有多个相同类型的对象时,使用@Autowired注解来装配对象会出现装配异常;并不能根据对象id来装配对象;想要根据对象id来装配对象需要借助@Qualifier注解来指定id名称,
@Component("userController") // 注册UserController到IOC容器,id默认为类名首字母小写
public class UserController {
@Autowired
@Qualifier("userService") //@Qualifier不能单独使用,配合Autowired使用
private UserService userService;
public User findById(Integer id){
return userService.findById(id);
}
}
Tips:
- 1)@Qualifier必须搭配@Autowired注解使用,不能单独使用
- 2)@Autowired注解在装配对象时,如果IOC容器中存在多个一样类型的对象,默认取类名首字母小写的对象进行装配;
1.4.4 @Resource注解
@Resource注解是Spring框架支持Sun官方制定的JSR-250标准注入对象的实现。
@Resource 功能等同 @Autowired + @Qualifier ,等同配置文件标签 <proprty name="..." ref="...">
@Resource注解:用于给引用注入容器的对象,可以通过name属性指定对象名
@Resource(name = "userService") // @Autowired+ @Qualifier()
private UserService userService;
Tips:@Resource注解只能注入方法和属性,不能注入构造方法
1.4.6 @Value注解
value只能设置,普通类型=基础数据类型+包装类+String
@Value注解:注入基本数据类型以及它们的包装类和String类型数据的,
支持${}
注入Properties文件的键值对,等同 <proprty name="..." value="${Key}">
- 定义一个MyDataSource:
package com.dfbz;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@Component
public class MyDataSource {
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driverClassName}")
private String driverClassName;
public void print(){
System.out.println("username: "+username);
System.out.println("password: "+password);
System.out.println("url: "+url);
System.out.println("driverClassName: "+driverClassName);
}
}
- 测试类:
@Test
public void test3(){
ApplicationContext app=new ClassPathXmlApplicationContext("spring2.xml");
MyDataSource dataSource = app.getBean(MyDataSource.class);
dataSource.print();
}
属性value:注入基本数据类型和String类型数据的
1.5 作用域相关注解
Spring是通过@Scope注解来指定对象的作用域的。
-
回顾Bean的生命周期:
- singleton:单例(默认值),容器创建时bean初始化,容器关闭时销毁;
- prototype:多例,等到用到的时候再初始化,容器关闭时不会销毁,自行销毁;
- reqeust:在WEB环境中,一次请求创建一次;
- session:在WEB环境中,一次会话创建一次;
- application:在WEB环境中,创建了一个上下文对象的时候创建该对象;
-
创建实体类:
@Component
@Scope("prototype") // 多例
public class Article {
private Integer id;
private String title;
private String author;
}
- 测试类:
package com.dfbz.demo;
import com.dfbz.entity.Article;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo05 {
ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("spring2.xml");
@Test
public void test1(){
Article bean1 = app.getBean(Article.class);
Article bean2= app.getBean(Article.class);
System.out.println(bean1 == bean2); // false
app.close();
}
}
1.6 生命周期相关注解
- @PostConstruct注解
等同于<bean init-method="">
作用:用于指定初始化方法。
- @PreDestroy注解
等同于<bean destory-method="">
作用:用于指定销毁方法。
- 修改Article实体类:
@Component
@Scope("singleton") // 多例
public class Article {
private Integer id;
private String title;
private String author;
/**
* 初始化方法
*/
@PostConstruct
public void init(){
System.out.println("article初始化了");
}
/**
* 销毁方法
*/
@PreDestroy
public void destroy(){
System.out.println("article销毁了");
}
}
二、纯注解开发
2.1 配置相关注解
我们发现,之所以我们现在离不开xml配置文件,是因为我们有一句很关键的配置:
<!-- 告知spring框架在,读取配置文件,创建容器时,扫描注解,依据注解创建对象,并存入容器中 -->
<context:component-scan base-package="com.dfbz" />
<!--加载jdbc.properties配置文件-->
<context:property-placeholder location="jdbc.properties" />
配置相关注解如下:
替换XML配置文件的@Configuration注解 | @Configuration配置类注解,在纯注解配置中,类加了该注解,就意味着该类是Spring的配置类。该类的功能就是用于替代原来的XML配置文件。 作用:用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解。获取容器时需要使用AnnotationConfigApplicationContext(有@Configuration注解的类.class)。 |
---|---|
@ComponentScan注解 | @ComponentScan注解扫描类,作用就是配置扫描Spring组件类的路径。功能等同原来配置文件的 –作用:用于指定spring在初始化容器时要扫描的包。作用和在spring的xml配置文件中的:<context:component-scan base-package=“com”/>是一样的。–属性:basePackages:用于指定要扫描的包。和该注解中的value属性作用一样。 |
@PropertySource注解 | 作用:用于加载.properties文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到properties配置文件中,就可以使用此注解指定properties配置文件的位置。属性:value[]:用于指定properties文件位置。如果是在类路径下,需要写上classpath:encoding:用于指定文件编码 |
@Bean注解 | 作用:该注解只能写在方法上,使用此方法创建一个对象,并且放入spring容器。它就相当于我们之前在xml配置中介绍的<bean标签> 属性:name:给当前@Bean注解方法创建的对象指定一个名称(即bean的id)。 |
@Import注解 | 作用:用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration注解。当然,写上也没问题。 属性:value[]:用于指定其他配置类的字节码。 |
2.2 使用纯注解改造xml方式
- 创建配置类:
package com.dfbz;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import javax.sql.DataSource;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@Configuration // 标注该类是一个配置类
@ComponentScan("com.dfbz") // 包扫描
@PropertySource("jdbc.properties") // 加载properties文件
public class SpringConfig {
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driverClassName}")
private String driverClassName;
/**
* 配置数据源
* @return
*/
@Bean // 相当于<bean>标签
public DataSource dataSource(){
DruidDataSource dataSource=new DruidDataSource();
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setUrl(url);
dataSource.setDriverClassName(driverClassName);
return dataSource;
}
}
复制之前的UserController、UserService、UserDao、User实体类、jdbc.properties等;
- 测试类:
package com.dfbz.test;
import com.dfbz.SpringConfig;
import com.dfbz.controller.UserController;
import com.dfbz.entity.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo01 {
@Test
public void test1(){
// 创建IOC容器,并指定配置类
ApplicationContext app=new AnnotationConfigApplicationContext(SpringConfig.class);
UserController userController = app.getBean(UserController.class);
User user = userController.findById(1);
System.out.println(user);
}
}
2.3 @Import注解
@Import注解主要的功能就是往IOC容器里面配置Bean,并且只能标注在类上;
2.3.1 @Import注解用法
1)直接配置
- 修改SpringConfig配置类:
@Configuration // 标注该类是一个配置类
@ComponentScan("com.dfbz") // 包扫描
@PropertySource("jdbc.properties") // 加载properties文件
@Import({UserDao.class, UserService.class}) // 直接配置两个bean到IOC容器中
public class SpringConfig {
....
}
注释UserDao、UserService上的@Repository、@Service注解;执行测试类;
2)ImportSelector配置
编写一个导入器类,实现ImportSelector
接口;
- 导入器:
package com.dfbz.selectors;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* @author lscl
* @version 1.0
* @intro: 编写一个配置导入器,指定需要导入的全类名
*/
public class MySelectors implements ImportSelector {
/**
* 导入具体的bean
* @param annotationMetadata: 获取注解的一些元信息
* @return
*/
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 要导入类的全类名
return new String[]{"com.dfbz.service.UserService","com.dfbz.dao.UserDao"};
}
}
配置类:
@Configuration // 标注该类是一个配置类
@ComponentScan("com.dfbz") // 包扫描
@PropertySource("jdbc.properties") // 加载properties文件
@Import({MySelectors.class}) // 指定导入器导入
public class SpringConfig {
}
3)ImportBeanDefinitionRegistrar配置
和ImportSelector方式类似,由自己往IOC容器中注册bean,可以定义bean的名称;
- 编写导入器:
package com.dfbz.selectors;
import com.dfbz.dao.UserDao;
import com.dfbz.service.UserService;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class MySelectors2 implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
//指定bean定义信息(包括bean的类型、作用域...)
RootBeanDefinition userDaoBeanDefinition = new RootBeanDefinition(UserDao.class);
//注册一个bean指定bean名字(id)
beanDefinitionRegistry.registerBeanDefinition("userDao",userDaoBeanDefinition);
//指定bean定义信息(包括bean的类型、作用域...)
RootBeanDefinition userServiceBeanDefinition = new RootBeanDefinition(UserService.class);
//注册一个bean指定bean名字(id)
beanDefinitionRegistry.registerBeanDefinition("userService",userServiceBeanDefinition);
}
}
三、Spring整合JdbcTemplate
3.1 项目搭建
- 导入依赖
<?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.dfbz</groupId>
<artifactId>03_Spring</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!--jdbcTemplate依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.1</version>
</dependency>
</dependencies>
</project>
复制之前的项目,把注解全部剔除;
3.1 使用xml方式整合
UserDao:
package com.dfbz.dao;
import com.dfbz.entity.User;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class UserDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* 新增
* @param user
*/
public void save(User user) {
jdbcTemplate.update("insert into user values(null,?,?)", user.getUsername(), user.getPassword());
}
/**
* 删除
* @param id
*/
public void delete(Integer id) {
jdbcTemplate.update("delete from user where id=?", id);
}
/**
* 修改
* @param user
*/
public void update(User user) {
jdbcTemplate.update("update user set username=?,password=? where id=?", user.getUsername(), user.getPassword(), user.getId());
}
/**
* 根据id查询(自动映射)
* @param id
* @return
*/
public User findById(Integer id) {
try {
// 最好抓一下异常,因为jdbctemplate没有查询任何的数据不是返回null,而是抛出异常
return jdbcTemplate.queryForObject("select * from user where id=?", new BeanPropertyRowMapper<>(User.class), id);
} catch (DataAccessException e) {
e.printStackTrace();
}
return null;
}
/**
* 根据id查询返回map类型
* @param id
* @return
*/
public Map<String, Object> findUserMapById(Integer id) {
try {
// 最好抓一下异常,因为jdbctemplate没有查询任何的数据不是返回null,而是抛出异常
return jdbcTemplate.queryForMap("select * from user where id=?",id);
} catch (DataAccessException e) {
e.printStackTrace();
}
return null;
}
/**
* 查询全部(自动映射)
* @return
*/
public List<User> findAll() {
return jdbcTemplate.query("select * from user ", new BeanPropertyRowMapper<>(User.class));
}
/**
* 查询全部手动映射,方式一
* @return
*/
public List<User> findAll2() {
return jdbcTemplate.query("select * from user ", new RowMapper<User>() {
/**
* 这个方法会执行很多次,将此次SQL语句查询到的每一条记录都封装到ResultSet中
* @param rs: 查询到的一行数据
* @param i :遍历的次数
* @return
* @throws SQLException
*/
@Override
public User mapRow(ResultSet rs, int i) throws SQLException {
return new User(rs.getInt("id"),rs.getString("username"),rs.getString("password"));
}
});
}
/**
* 查询全部手动映射,方式二
* @return
*/
public List<User> findAll3() {
return jdbcTemplate.query("select * from user ", new ResultSetExtractor<List<User>>() {
/**
* 这个方法只会执行一次,将此次SQL语句查询的所有结果集都封装到ResultSet中
* @param rs
* @return
* @throws SQLException
* @throws DataAccessException
*/
@Override
public List<User> extractData(ResultSet rs) throws SQLException, DataAccessException {
List<User> userList=new ArrayList<>();
while (rs.next()){
userList.add(new User(rs.getInt("id"),rs.getString("username"),rs.getString("password")));
}
return userList;
}
});
}
/**
* 查询全部返回map结果
* @return
*/
public List<Map<String, Object>> findUserMapAll() {
return jdbcTemplate.queryForList("select * from user");
}
/**
* 查询单个
* @return
*/
public Long count() {
return jdbcTemplate.queryForObject("select count(1) from user",Long.class);
}
}
spring.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--加载jdbc.properties配置文件-->
<context:property-placeholder location="jdbc.properties" />
<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="url" value="${jdbc.url}" />
<property name="driverClassName" value="${jdbc.driverClassName}" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置userDao-->
<bean id="userDao" class="com.dfbz.dao.UserDao">
<!--要提供set方法-->
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<bean id="userService" class="com.dfbz.service.UserService">
<!--注入userDao-->
<!--要提供set方法-->
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userController" class="com.dfbz.controller.UserController">
<!--注入userService-->
<!--要提供set方法-->
<property name="userService" ref="userService" />
</bean>
</beans>
- 测试类:
package com.dfbz.test;
import com.dfbz.controller.UserController;
import com.dfbz.entity.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo01 {
// 创建IOC容器,并指定配置类
ApplicationContext app=new ClassPathXmlApplicationContext("spring.xml");
UserController userController = app.getBean(UserController.class);
@Test
public void test1(){
User user = userController.findById(1);
System.out.println(user);
}
}
3.2 xml和注解混用
在xml中去除注入,使用@autowired注解注入
spring.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描包-->
<context:component-scan base-package="com.dfbz" />
<!--加载jdbc.properties配置文件-->
<context:property-placeholder location="jdbc.properties" />
<!--配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="url" value="${jdbc.url}" />
<property name="driverClassName" value="${jdbc.driverClassName}" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
3.3 使用纯注解
- 新建配置类:
package com.dfbz;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@Configuration
@ComponentScan("com.dfbz")
@PropertySource("jdbc.properties")
public class SpringConfig {
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driverClassName}")
private String driverClassName;
/**
* 配置数据源
* @return
*/
@Bean
public DataSource dataSource(){
DruidDataSource dataSource=new DruidDataSource();
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setUrl(url);
dataSource.setDriverClassName(driverClassName);
return dataSource;
}
/**
* 配置JdbcTemplate
* @param dataSource
* @return
*/
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource){
return new JdbcTemplate(dataSource);
}
}
- 测试类:
package com.dfbz.test;
import com.dfbz.SpringConfig;
import com.dfbz.controller.UserController;
import com.dfbz.entity.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo02 {
// 创建IOC容器,并指定配置类
ApplicationContext app=new AnnotationConfigApplicationContext(SpringConfig.class);
UserController userController = app.getBean(UserController.class);
@Test
public void test1(){
User user = userController.findById(1);
System.out.println(user);
}
}
四、Spring整合Junit
在测试类中,每个测试方法都有以下两行代码:
ApplicationContext app = new ClassPathXmlApplicationContext("application.xml");
UserController userController = app.getBean(UserController.class);
这两行代码的作用是获取容器,比较繁琐,如何解决?
针对上述问题,我们需要的是程序能自动帮我们创建容器。一旦程序能自动为我们创建 spring 容器,我们就无须手动创建了,问题也就解决了。
但显然, junit 是无法实现的,因为它自己都无法知晓我们是否使用了 spring 框架,更不用说帮我们创建 spring 容器了。
不过好在, junit 给我们暴露了一个注解,可以让我们替换掉它的运行器。这时,我们需要依靠 spring 框架,因为它提供了一个运行器,可以读取配置文件(或注解)来创建容器。
4.1. 测试基于XML的配置
4.1.1 创建项目引入依赖
<!-- spring整合junit包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
4.1.2 创建实体类
public class User {
private Integer id;
private String username;
private String password;
public User() {
}
public User(Integer id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
}
4.1.3 编写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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="user" class="com.dfbz.entity.User">
<property name="id" value="1"></property>
<property name="username" value="zhangsan"></property>
<property name="password" value="123"></property>
</bean>
</beans>
4.1.4 测试类
package com.dfbz.test;
import com.dfbz.entity.User;
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.SpringRunner;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class Demo01 {
@Autowired
private User user;
@Test
public void test(){
System.out.println(user);
}
}
4.2 基于注解的配置
4.2.1 修改User实体类:
@Component
public class User {
@Value("1")
private Integer id;
@Value("zhangsan")
private String username;
@Value("123")
private String password;
}
4.2.2 spring配置类
package com.dfbz;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@Configuration
@ComponentScan("com.dfbz") // 包扫描
public class SpringConfig {
}
4.2.3 测试类
package com.dfbz.test;
import com.dfbz.SpringConfig;
import com.dfbz.entity.User;
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.SpringRunner;
/**
* @author lscl
* @version 1.0
* @intro:
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = SpringConfig.class) // 换成配置类
public class Demo02 {
@Autowired
private User user;
@Test
public void test(){
System.out.println(user);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/131663.html