纯注解形式开发Spring(整合MyBatis)
【前言】经过之前的纯配置形式开发Spring,我们发现,通过纯配置来开发十分的复杂,代码量较多,开发效率较低。接下来,我们使用Spring注解来开发Spring,提高开发效率。
本文所有文件如下:
链接:https://pan.baidu.com/s/1sqU9ADUkq-BleeWyNh1YoQ
提取码:kdyo
1、创建Maven工程,导入相关依赖(pom.xml):
此处和通过纯配置形式开发Spring所用的依赖是一样的,具体使用原因请参考:http://t.csdn.cn/UTc2Q
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.24</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
</dependency>
</dependencies>
2、创建数据库(student)和实体类(User):
此处和纯配置一样,不做解释。
2.1、数据库配置(jdbc.properties)
# 数据库驱动名:driverClassName
jdbc.driver=com.mysql.jdbc.Driver
# 路径
jdbc.url=jdbc:mysql://localhost:3306/test02?useSSL=false
# 用户名和密码
jdbc.username=root
jdbc.password=root
2.2、数据库(student):
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`age` int(11) NOT NULL,
`gender` int(2) NULL DEFAULT NULL COMMENT '0:女,1:男',
`idNumber` varchar(18) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `id_student_idNumber`(`idNumber`) USING BTREE,
INDEX `idx_student_name`(`name`) USING BTREE,
INDEX `id_age_gender`(`age`, `gender`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (2, '李四', 20, 1, '121234567812345678');
INSERT INTO `student` VALUES (3, '王五', 21, 0, '131234567812345678');
INSERT INTO `student` VALUES (4, '赵六', 22, 0, '141234567812345678');
INSERT INTO `student` VALUES (5, '王五大', 21, 1, '151234567812345678');
INSERT INTO `student` VALUES (6, '阿迪斯', 22, 0, '161234567812345678');
INSERT INTO `student` VALUES (7, '维奇', 19, 1, '171234567812345678');
INSERT INTO `student` VALUES (8, '撒旦', 20, 0, '181234567812345678');
INSERT INTO `student` VALUES (9, '阿斯顿', 18, 1, '191234567812345678');
INSERT INTO `student` VALUES (10, '大苏打', 18, 1, '201234567812345678');
INSERT INTO `student` VALUES (11, '大撒在', 18, 0, '211234567812345678');
SET FOREIGN_KEY_CHECKS = 1;
2.3、创建实体类(User):
【注】此处我们需要导入lombok依赖:
- 概念:Lombok是一个Java库,他通过注解来简化Java代码的编写,减少了重复代码的书写,提高了代码的可读性和可维护性。
- 作用:
- 可以自动生成getter和setter方法:使用@Getter和@Setter注解可以自动生成实体类的getter和setter方法。
- 自动生成toString方法:使用@ToString注解可以自动生成toString方法。
- 自动生成equals和hashCode方法:使用@EqualsAndHashCode注解。
- 注意:上述这些注解都可以通过==@Data==注解来代替,使用@Data注解可以自动生成getter、setter、equals、hashCode和toString方法。极大的简化了代码书写。
- 自动生成构造方法:使用@AllArgsConstructor注解可以自动生成所有参数的构造方法。
- 自动生成日志输出:使用@Slf4j注解可以自动生成日志输出的代码。
- 简化异常处理:使用@SneakyThrows注解可以自动抛出指定类型的异常。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
</dependency>
package com.it.pojo;
import lombok.Data;
@Data
public class User {
private Integer id;
private String name;
private Integer age;
private Integer gender;
private String idNumber;
}
3、介绍几种常用注解(重点):
-
@Component:用于将一个类标识为Spring的组件,以便让Spring的配置文件自动扫描并注册为Spring bean
原理:使用Java的反射机制,通过指定扫描指定的包路径,找到所有被改注解标记的类,并将其实例化文bean对象
@Component public class UserService(){ // ... }
- @Controller:原理和@Component注解一样,只是该注解只用于标记控制层的文件。在Spring MVC中,使用了该注解标记的类会被自动扫描并注册为处理HTTP请求和响应的控制器。
- @Service:原理和@Component注解一样,只是该注解只用于标记业务层实现类,用于处理业务逻辑。
- @Repository:原理和@Component注解一样,只是该注解用于标记数据访问层,用于数据库访问,对数据库进行操作。
-
@Autowired:用于自动装配Spring bean,可以用于构造方法、属性、方法参数上。
原理:@Autowired注解是Spring的依赖注入的实现原理。当Spring容器初始化时,会自动查找陪陪类型的bean,并将器注入到@Autowired注解标记的属性、构造方法或参数中。
@Autowired private UserService userService;
-
@Qualifier:用于指定注入的Spring bean的名称或限定符,用于解决自动装配时的歧义性。
原因:因为@Autowired不带任何参数的话,默认是按类型装配,当一个接口存在多个实现类时,不指定具体名称的话就会抛出异常:NoUniqueBeanDefinitionException。
@Autowired @Qualifier("userServiceImpl1") private UserService userService;
-
@Value:用于属性值注入,可以用于构造方法、属性、方法参数上。
@Value("张三") private String username;
-
@Configuration:用于将一个类标识为Spring的配置文件,用于配置Spring bean
@Configuration public class SpringConfig{ }
-
@Bean:用于将以个方法标识为一个Spring bean的定义,通常用于配置类中
@Bean public DataSource dataSource(){ // ... }
-
@ComponentScan:用于指示Spring容器扫描指定的包及其子包,自动注册被标注的组件(如:@Component、@Service、@Repository)为Spring的bean。
在Spring中,使用该注解可以告诉Spring容器去哪些包中寻找组件,然后将这些组件注册为Spring bean。这样,通过@Autowired注解进行自动注入式,Spring就能够自动找到对应的bean进行注入。通常和@Configuration注解一起用。它的一些参数如下:
- basePackages:指定要扫描的包名数组。
- basePackageClasses:指定要扫描的类数组,Spring根据这些类所在的包进行扫描。
- includeFilters:指定要包含的组件类型,可以是注解、接口或类。
- excludeFilters:指定要排除的组件类型。
@Configuration @ComponentScan("com.it") public class SpringConfig{ }
-
@Import:用于在配置类中导入其他的配置类或组件。使用@Import注解可以将其他类型配置类或组件引入到当前的配置类中,以便在Spring容器中进行注册和管理。被导入的配置类可以是包含其他的bean定义、组件扫描、AOP配置等。有多个需要使用 {} 包含。
@Configuration @ComponentScan("com.it") @Import({JdbcConfig.class, MyBatisConfig.class}) public class SpringConfig{ }
-
@PorpertySource:用于指定外部属性文件。例如:数据库连接信息文件,日志级别文件等。
@Configuration @PropertySource("classpath:jdbc.properties") public class SpringConfig{ }
-
暂时介绍这些,其他以后使用再具体介绍!
4、创建数据访问层接口类和映射文件(UserDao.java、UserDao.xml):
4.1、数据访问层接口类:
使用@Repository注解标记,标识它是一个用于操作数据库的类。也可以使用@Component注解。
package com.it.dao;
import com.it.pojo.User;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserDao {
// 查询所有
List<User> selectAll();
// 根据id查询
User selectById(Integer id);
// 添加用户
int save(User user);
// 修改
int updateById(User user);
// 删除
int deleteById(Integer id);
}
4.2、映射文件:
和纯配置一样,定义SQL语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.it.dao.UserDao">
<!--查询所有-->
<select id="selectAll" resultType="User">
select * from student;
</select>
<!--根据id查询-->
<select id="selectById" resultType="user">
select * from student where id = #{id};
</select>
<!--添加用户-->
<insert id="save" useGeneratedKeys="true" keyProperty="id">
insert into student(name, age, gender, idNumber) value(#{name}, #{age}, #{gender}, #{idNumber});
</insert>
<!--修改-->
<update id="updateById">
update student
<set>
<if test="name != null and name != '' ">
name = #{name},
</if>
<if test="age != null">
age = #{age},
</if>
<if test="gender != null">
gender = #{gender},
</if>
<if test="idNumber != null and idNumber != '' ">
idNumber = #{idNumber},
</if>
</set>
where id = #{id};
</update>
<!--删除-->
<delete id="deleteById">
delete student where id = #{id};
</delete>
</mapper>
5、创建业务层接口及其实现类(UserService、UserServiceImpl):
5.1、业务层接口:
此处暂时先不处理事务,有需求的自行处理。
package com.it.service;
import com.it.pojo.User;
import java.util.List;
public interface UserService {
// 查询所有
List<User> selectAll();
// 根据id查询
User selectById(Integer id);
// 添加用户
boolean save(User user);
// 修改
boolean updateById(User user);
// 删除
boolean deleteById(Integer id);
}
5.2、实现类:
使用@Service注解标记,表示该类是一个业务层,由于处理业务逻辑的bean。
使用@Autowired注解实现自动装配。
package com.it.service.impl;
import com.it.dao.UserDao;
import com.it.pojo.User;
import com.it.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public List<User> selectAll() {
return userDao.selectAll();
}
@Override
public User selectById(Integer id) {
return userDao.selectById(id);
}
@Override
public boolean save(User user) {
return userDao.save(user) > 0;
}
@Override
public boolean updateById(User user) {
return userDao.updateById(user) > 0;
}
@Override
public boolean deleteById(Integer id) {
return userDao.deleteById(id) > 0;
}
}
6、配置类(重点):
6.1、数据源配置(JdbcConfig.java):
此处使用DataSource接口,调用其实现类DruidDataSource,实现数据源信息的注入。同时需要使用@Bean注解将其标记为一个bean对象。
package com.it.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class JdbcConfig {
@Value("${jdbc.driver}")
String driver;
@Value("${jdbc.url}")
String url;
@Value("${jdbc.username}")
String username;
@Value("${jdbc.password}")
String password;
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
6.2、mybatis配置(MyBatisConfig.java):
使用SqlSessionFactoryBean来进行设置别名,以及添加数据源对象;使用MapperScannerConfigrurer扫描sql映射文件。
package com.it.config;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class MyBatisConfig {
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setTypeAliasesPackage("com.it.pojo");
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
// 此处扫描的的映射文件,不是接口文件
mapperScannerConfigurer.setBasePackage("com.it.dao");
return mapperScannerConfigurer;
}
}
6.3、Spring配置文件(SpringConfig.java):
将所有的配置信息都交给Spring容器来进行管理。
package com.it.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
@Configuration
@ComponentScan("com.it")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MyBatisConfig.class})
public class SpringConfig {
}
7、控制层:
package com.it.web;
import com.it.config.SpringConfig;
import com.it.pojo.User;
import com.it.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.List;
public class UserApp {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService = applicationContext.getBean(UserService.class);
// 查询全部
List<User> users = userService.selectAll();
for (User user :
users) {
System.out.println(user);
}
// 根据id查询
User user = userService.selectById(2);
System.out.println(user);
// 添加
User user1 = new User();
user1.setName("王俊生");
user1.setAge(21);
user1.setGender(1);
user1.setIdNumber("0987789012341234");
boolean flag1 = userService.save(user1);
if (flag1) {
System.out.println("添加成功");
System.out.println(userService.selectById(user1.getId()));
} else {
System.out.println("添加失败");
}
// 修改
User user2 = new User();
user2.setId(2);
user2.setAge(18);
user2.setName("李四666");
boolean flag2 = userService.updateById(user2);
if (flag1) {
System.out.println("修改成功");
System.out.println(userService.selectById(user2.getId()));
} else {
System.out.println("修改失败");
}
// 删除
System.out.println(userService.selectById(2));
userService.deleteById(2);
System.out.println(userService.selectById(2));
}
}
8、纯配置形式开发和纯注解开发的对比:
-
实体类编写:
-
数据访问层编写:
-
业务层:
-
配置文件:
【综上】使用注解形式开发Spring比使用配置形式开发Spring效率更高,代码量少,建议使用注解形式开发Spring。