目录
第五步:编写数据源配置类(目的:返回一个数据源bean对象)
这里也许就会有人疑惑:明明没有把StudentMapper类交给spring管理,为什么可以直接ctx.getBean(StudentMapper.class);获取bean对象?
1. jdbc.propetties配置文件中所有属性名加上前缀,如
项目大致结构:
Spring整合mybatis开发步骤
第一步:创建我们的数据表
第二步:编写对应的实体类
public class Student {
private Integer id;
private String name;
private Integer age;
public Student() {
}
public Student(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
第三步:在pom.xml中导入我们所需要的坐标
spring所依赖的坐标
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.10.RELEASE</version> </dependency> <!-- spring数据层依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.10.RELEASE</version> </dependency>
mybatis所依赖的坐标
<!--导入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.0</version> </dependency>
druid数据源坐标
<!-- 导入druid数据源--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency>
数据库驱动依赖
<!-- 导入连接--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.13</version> </dependency>
第四步:编写SpringConfig配置类
@Configuration
@ComponentScan("com.hhh")
@PropertySource("classpath:jdbc.properties")
@Import({MybatisConfig.class,JdbcConfig.class})
public class SpringConfig {
}
- @Configuration说明这是一个配置类
- @ComponentScan("com.hhh")说明spring要扫描(管理)的范围
- @@PropertySource("classpath:jdbc.properties")全局引入外部文件
- @Import({MybatisConfig.class,JdbcConfig.class})导入外部配置类
第五步:编写数据源配置类(目的:返回一个数据源bean对象)
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String name;
@Value("${jdbc.password}")
private String password;
//让返回的druid数据源对象成为bean
@Bean
public DataSource getDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driver);
druidDataSource.setUsername(name);
druidDataSource.setUrl(url);
druidDataSource.setPassword(password);
return druidDataSource;
}
}
我在这个配置类中写了一个getDataSource()方法,并加上@Bean注解,目的是让这个方法的返回值成为一个Bean对象
- druidDataSource.setDriverClassName(driver);
- druidDataSource.setUsername(name);
- druidDataSource.setUrl(url);
- druidDataSource.setPassword(password);
这四行分别配置了连接数据库的四大参数,这四大参数通过@Value的方式进行注入
第六步:编写MybatisConfig配置类
public class MybatisConfig {
//使用了mybatis整合bean的工厂类,不然会报错
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
//直接在参数上写需要的数据源类型,spring会根据bean的类型自动依赖注入
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
//设置别名,让com.hhh.pojo这个包下的类只需要写类名即可
sqlSessionFactoryBean.setTypeAliasesPackage("com.hhh.pojo");
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
/**
* 创建 MapperScannerConfigurer Mapper类对象,用来加载dao层接口
* @return
*/
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//扫描mapper
mapperScannerConfigurer.setBasePackage("com.hhh.dao");
return mapperScannerConfigurer;
}
}
这个配置类有两个目的:
1.返回一个SqlSessionFactory工厂类Bean对象
2.扫描dao层的接口文件
所以我写了两个方法
第一个方法:返回值类型要写成SqlSessionFactoryBean,这是mybatis整合bean的工厂类
不能只写SqlSessionFactory
在这个方法里配置了所有实体类的别名和配置了所需要的数据源
第二个方法:扫描了dao层的所有mapper接口文件,并返回MapperScannerConfigurer类型的bean对象
第七步:编写dao层的接口文件
public interface StudentMapper { //根据id查询 @Select("select id,name,age from student where id =#{id};") Student findById(@Param("id")Integer id); }
第八步:编写测试类
public class App {
public static void main(String[] args) {
//加载配置类
ApplicationContext ctx= new AnnotationConfigApplicationContext(SpringConfig.class);
StudentMapper studentMapper = ctx.getBean(StudentMapper.class);
Student student = studentMapper.findById(1);
System.out.println(student);
}
}
结果:
这里也许就会有人疑惑:明明没有把StudentMapper类交给spring管理,为什么可以直接ctx.getBean(StudentMapper.class);获取bean对象?
我们先来打印一个这个studentMapper对象看看
MapperProxy接口代理对象,可见spring帮我们创建了一个 MapperProxy类型的bean,这是哪里创建的?
这就是MybatisConfig配置类中mapperScannerConfigurer()方法通过扫描dao层的所有接口文件时创建的。
错误分析
第一个错误
com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl info
信息: {dataSource-1} inited
7月 20, 2024 12:05:46 下午 com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl error
严重: create connection SQLException, url: jdbc:mysql://localhost:3306/mysql_day2?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false, errorCode 1045, state 28000
java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
无限循环报以上的错误
解决方法:
1. jdbc.propetties配置文件中所有属性名加上前缀,如
2.注意看你写的配置文件里有没有多余的空格
3.数据库驱动和数据库版本不一致
select VERSION();查询数据库版本
<!-- 导入连接--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.13</version> </dependency>
这里我因为之前下载的数据库为8.30,没有这个高版本的数据库驱动,所以我还重新安装了数据库,哭
4.数据库驱动
mysql5 使用的驱动为 com.mysql.jdbc.Driver
mysql8 使用的驱动为 com.mysql.cj.jdbc.Driver
我在使用了上述四种方法后还是报错,
继续试了不使用外部文件,直接注入,依旧不行,把密码改成root,也不行,当时真的快崩溃了
,但是我没有放弃,继续查看报错
errorCode 1045, state 28000
我通过查询大量文章的得知1045时用户名和密码错误,但是我的配置文件里的用户名和密码都是正确的,所以我注意到了上面红字的部分,我看到别人的报错在@前面都会有他们自己的数据库用户名,但是我的没有显示用户名,我就在想是不是数据源的用户名没有传进去。我查看
通过对比发现setName()并不是配置用户名的,我马上修改成
最后运行正确,历时一个下午,一个晚上(甚至做梦梦到),最后在早晨醒来时豁然开朗,发现错误。
还有第二个错误
create connection SQLException, url: jdbc:mysql://localhost:3306/mysql_day2, errorCode 0, state 01S00
java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
解决方法:
在url后面加上 ?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false
完整的jdbc.properties配置文件
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mysql_day2?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false jdbc.username=root jdbc.password=123456
Spring整合junit
导入所需要的依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.10.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
测试
//添加spring整合junit专用的类加载器
@RunWith(SpringJUnit4ClassRunner.class)
//加载spring配置类
@ContextConfiguration(classes= SpringConfig.class)
public class Test {
@Autowired
private StudentMapper studentMapper;//这里会一直报错No beans of 'StudentMapper' type found.
//但是我们通过MybatisConfig配置类扫描了dao层的所有接口,会创建出一个代理类bean,所以不用管
@org.junit.Test
public void testFindById(){
Student student = studentMapper.findById(1);
System.out.println(student);
}
}
结果: