四.SpringBoot 数据访问
1.简介
SpringBoot底层采用了Spring Data框架操作数据
2. JDBC
-
使用Spring Initializer创建项目
-
选中Web,Mysql,JDBC模块并生成项目
-
生成的项目不能直接运行,因为我们导入了数据库相关的依赖,必须配置数据库才能正常启动
-
配置数据库相关
#spring配置 spring: #数据库相关 datasource: url: jdbc:mysql:///live?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC username: huanqwer password: zhz521 driverClassName: com.mysql.cj.jdbc.Driver
-
如果没有指定自己的数据源,SpringBoot官方默认使用Tomcat连接池作为我们的数据源,我们也可以用spring.datasource.type指定我们自己的数据源(c3p0,dbcp,Druid等)
-
Tomcat连接池简单的配置示例
#spring配置 spring: #数据库相关 datasource: url: jdbc:mysql:///live?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC username: huanqwer password: zhz521 driverClassName: com.mysql.cj.jdbc.Driver max-active: 20 max-idle: 8 min-idle: 8 initial-size: 20
3. 整合自己的数据源
整合阿里的Druid数据源
-
去Maven Repo上找到最新版的Druid依赖
<!--druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.19</version> </dependency>
-
引入后我们的项目会报错,无法启动,是因为数据源没有切换过来
-
我们使用type指定DruidDataSource
-
找到Druid引入包下面的DataSource
-
引入后的yml如下
#系统端口 server: port: 80 #spring配置 spring: #数据库相关 datasource: url: jdbc:mysql:///live?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC username: huanqwer password: zhz521 driverClassName: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource #全站配置 site: url : localhost updatePath : update suId : '0033081800192' drId : '0024062400084' smsDeadTime : 5 smsNum: 5
-
运行后切换数据源成功!
-
对数据源进行配置
参考文献,只参考配置部分(文档中的filters配置是错误的,需要定义为数组)
https://blog.csdn.net/weixin_43453386/article/details/83582399
# 初始化连接池个数 initialSize: 5 # 最小连接池个数——》已经不再使用,配置了也没效果 minIdle: 2 # 最大连接池个数 maxActive: 20 # 配置获取连接等待超时的时间,单位毫秒,缺省启用公平锁,并发效率会有所下降 maxWait: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 timeBetweenEvictionRunsMillis: 60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 minEvictableIdleTimeMillis: 300000 # 用来检测连接是否有效的sql,要求是一个查询语句。 # 如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用 validationQuery: SELECT 1 FROM DUAL # 建议配置为true,不影响性能,并且保证安全性。 # 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 testWhileIdle: true # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 testOnBorrow: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 testOnReturn: false # 打开PSCache,并且指定每个连接上PSCache的大小 poolPreparedStatements: true maxPoolPreparedStatementPerConnectionSize: 20 # 通过别名的方式配置扩展插件,多个英文逗号分隔,常用的插件有: # 监控统计用的filter:stat # 日志用的filter:log4j # 防御sql注入的filter:wall filters: [stat,wall,log4j] # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # 合并多个DruidDataSource的监控数据 useGlobalDataSourceStat: true
配置后并不会生效
因为默认不会识别,需要对应的配置类(没有参考文章里的,用我们之前的知识配置)
@Configuration public class DruidConfig { @ConfigurationProperties(prefix = "spring.datasource") @Bean public DataSource druid(){ return new DruidDataSource(); } }
然后在测试类中测试我们的配置是否生效
可见我们数据源已经替换成功
在数据源上打断点,查看配置详情
以debug模式运行
选择dataSource并查看对象属性
可见我们的配置已经被读取
-
配置Druid监控(参考CSDN文献)
/** * 主要实现WEB监控的配置处理 */ @Bean public ServletRegistrationBean druidServlet() { // 现在要进行druid监控的配置处理操作 ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean( new StatViewServlet(), "/druid/*"); // 白名单,多个用逗号分割, 如果allow没有配置或者为空,则允许所有访问 servletRegistrationBean.addInitParameter("allow", "127.0.0.1,172.29.32.54"); // 黑名单,多个用逗号分割 (共同存在时,deny优先于allow) servletRegistrationBean.addInitParameter("deny", "192.168.1.110"); // 控制台管理用户名 servletRegistrationBean.addInitParameter("loginUsername", "admin"); // 控制台管理密码 servletRegistrationBean.addInitParameter("loginPassword", "admin"); // 是否可以重置数据源,禁用HTML页面上的“Reset All”功能 servletRegistrationBean.addInitParameter("resetEnable", "false"); return servletRegistrationBean ; } @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean() ; filterRegistrationBean.setFilter(new WebStatFilter()); //所有请求进行监控处理 filterRegistrationBean.addUrlPatterns("/*"); //添加不需要忽略的格式信息 filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.css,/druid/*"); return filterRegistrationBean ; }
-
访问http://localhost/druid,用户名admin密码admin,进入后台监控
4. 整合Mybatis
-
重新创建项目,选择模块:web,lombok,dev-tools,processor,Mysql,JDBC,MyBatis
-
引入Druid(或者使用默认Tomcat连接池)
-
配置Druid
-
项目自动创建表
spring: datasource: schema: - classpath:sql/{tablename}.sql - classpath:sql/{tablename}.sql
项目启动后会自动跑sql语句创建表
注意:第二次运行时要把schema注掉!
4.1 注解版Mybatis
-
创建Mapper文件
@Mapper public interface BaseMapper { @Select("select * from user where u_gyh = #{gyh}") List<Map<String, Object>> getUserByGyh(String gyh); }
或者可以根据参数的顺序
@Mapper public interface BaseMapper { @Select("select * from user where u_gyh = #{arg0}") List<Map<String, Object>> getUserByGyh(String gyh); }
-
注解版插入后id为NULL
使用@Options注解
@Options(useGeneratedKeys = true,keyProperty = "id")
-
注解版开启批量别名定义
以前我们可以直接在xml中使用type_alias批量定义别名
但是在注解版里怎么配置呢?
@Configuration public class MybatisConfig { @Bean public ConfigurationCustomizer configurationCustomizer(){ return new ConfigurationCustomizer() { @Override public void customize(org.apache.ibatis.session.Configuration configuration) { configuration.setMapUnderscoreToCamelCase(true); } }; } }
同样,咱们可以在yml中直接配置
#mybatis驼峰命名 mybatis: configuration: map-underscore-to-camel-case: true
-
每个类加@Mapper注解太麻烦
在主程序上加@MapperScan
@SpringBootApplication @MapperScan("com.scj.mana.mapper") public class ManaApplication { public static void main(String[] args) { SpringApplication app = new SpringApplication(ManaApplication.class); app.setBannerMode(Banner.Mode.OFF); app.run(args); } }
-
创建对应实体太麻烦
可以使用Mybatis逆向工程为我们生成pojos,但是逆向工程师用于生成xml,所以接下来我们讲解配置版的Mybatis
4.2 配置版的Mybatis(略,放到后面讲)
-
添加逆向工程依赖
上maven repo上找到mybatis逆向工程依赖
<!--mybatis-generator-core --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.7</version> </dependency>
等待下载完成后在resources文件夹下创建逆向工程配置文件
巴拉巴拉…
4.3 整合Mybatis最佳实践
全注解开发中我们会发现在写insert语句会特别耗费时间
所以我们使用navicat中添加任意一条数据,然后赋值为insert语句
INSERT INTO `live`.`user`(`u_id`, `u_gyh`, `u_mobile`, `u_name`, `user_role`) VALUES (1, '0033081800192', '18641155202', '覃岭', NULL);
在此基础上修改也能降低出错概率
update同理
UPDATE `live`.`user` SET `u_gyh` = '0033081800192', `u_mobile` = '18641155202', `u_name` = '覃岭', `user_role` = NULL WHERE `u_id` = 1;
使用IDEA工具为我们逆向生成实体类
参考文献
https://blog.csdn.net/qq_27435059/article/details/52494623
如果找不到Persistance,我们可以选择项目后按F4,然后点击Modules>点击+号>选择JPA
记住务必下载驱动连接数据库!
生成的代码如下
@Entity
public class User {
private int uId;
private String uGyh;
private String uMobile;
private String uName;
private Integer userRole;
@Id
@Column(name = "u_id")
public int getuId() {
return uId;
}
public void setuId(int uId) {
this.uId = uId;
}
@Basic
@Column(name = "u_gyh")
public String getuGyh() {
return uGyh;
}
public void setuGyh(String uGyh) {
this.uGyh = uGyh;
}
@Basic
@Column(name = "u_mobile")
public String getuMobile() {
return uMobile;
}
public void setuMobile(String uMobile) {
this.uMobile = uMobile;
}
@Basic
@Column(name = "u_name")
public String getuName() {
return uName;
}
public void setuName(String uName) {
this.uName = uName;
}
@Basic
@Column(name = "user_role")
public Integer getUserRole() {
return userRole;
}
public void setUserRole(Integer userRole) {
this.userRole = userRole;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return uId == user.uId &&
Objects.equals(uGyh, user.uGyh) &&
Objects.equals(uMobile, user.uMobile) &&
Objects.equals(uName, user.uName) &&
Objects.equals(userRole, user.userRole);
}
@Override
public int hashCode() {
return Objects.hash(uId, uGyh, uMobile, uName, userRole);
}
}
因为我们有lombok
所以修改实体类的代码为
@Data
public class User {
private int uId;
private String uGyh;
private String uMobile;
private String uName;
private Integer userRole;
}
以上就是整个数据访问内容
以上博文是我在培训的时候整理的教案,码字不易,转载请注明出处,联系邮箱huanqwer0314@gmail.com