SpringBoot与数据访问
整合基本的JDBC
创建项目
在创建项目的时候选中SQL的JDBC跟MySQL
在pom.xml中会导入相应的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
编写数据库配置
要使用数据库得先编写用户名,密码,url跟驱动包
spring: datasource: username: root password: 123 url: jdbc:mysql://127.0.0.1:3306/jdbc driver-class-name: com.mysql.jdbc.Driver
DataSourceInitializer作用
在AppliationListener中有一个DataSourceInitializer,那么它的作用是什么呢?
-
runSchemaScripts();运行建表语句;
-
runDataScripts();运行插入数据的sql语句;
默认只需要将文件命名为:schema-*.sql跟data-*.sql即可(如果在SpringBoot2.x版本里面要在application.yml文件里面加上 initialization-mode: always),还可以通过schema指定文件加载的位置以及指定文件名
操作数据库(自动配置了jdbcTemplate)
做好上面的设置后,就可以直接使用jdbc了,由于SpringBoot为我们配好了jdbcTemplate,因此直接使用即可
@Autowired JdbcTemplate jdbcTemplate; @ResponseBody @GetMapping("/query") public Map<String, Object> maped(){ List<Map<String, Object>> maps = jdbcTemplate.queryForList("SELECT * FROM department"); return maps.get(0); }
整合Druid & 配置数据源监控
导入依赖
<!-- 引入druid数据源 --> <!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.8</version> </dependency>
切换数据源为DruidDataSource
想要将数据源切换成DruidDataSource只需要在application.yml文件中配置spring.datasource的type属性即可
spring: datasource: username: root password: 123 url: jdbc:mysql:///myjdbc?characterEncoding=UTF-8 driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource
只需要配置type属性,就可以将数据源切换
配置Druid相关属性
同样在application.yml中配置即可
spring: datasource: username: root password: 123 url: jdbc:mysql:///myjdbc?characterEncoding=UTF-8 driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource # schema: # - classpath:department.sql # initialization-mode: always # 下面为连接池的补充设置,应用到上面所有数据源中 # 初始化大小,最小,最大 initialSize: 5 minIdle: 5 maxActive: 20 # 配置获取连接等待超时的时间 maxWait: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 timeBetweenEvictionRunsMillis: 60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true # 配置监控统计拦截的filter,去掉后监控界面sql无法统计,'wall'用于防火墙 filters: stat, wall maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
但是配置的这些属性是不能够立即生效的,因为在DataSourceProerties中并没有这些属性,那么这时候就需要我们自己写一个配置类了
@Configuration public class MyConfig{ @ConfigurationProperties(prefix = "spring.datasource") @Bean public DataSource druidDataSource(){ return new DruidDataSource(); } }
经过上面的配置,写在application.yml中的文件才生效
配置Druid容器
除了上面那样在配置文件中配置相关属性,并在配置类中应用之外。还需要在配置类中配置一个后台管理的Servlet跟一个监控的Filter
而Servlet跟Filter可以在配置类中配置也可以使用注解配置,下面对这两种方式均做说明
使用配置类配置
// 配置Druid的监控 // 1、配置一个管理后台的Servlet @Bean public ServletRegistrationBean<StatViewServlet> statViewServlet(){ ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); // 配置参数 Map<String, String> initParams = new HashMap<>(); initParams.put("loginUsername", "admin"); // 登录名 initParams.put("loginPassword", "123"); // 登录密码 initParams.put("allow", ""); // 为空表示允许所有登录 // initParams.put("deny", "172.12.111.98"); // 拒绝谁访问 bean.setInitParameters(initParams); return bean; } // 2、配置一个监控的Filter @Bean public FilterRegistrationBean<WebStatFilter> webStatFilter(){ FilterRegistrationBean<WebStatFilter> bean = new FilterRegistrationBean<>(); bean.setFilter(new WebStatFilter()); bean.setUrlPatterns(Arrays.asList("/*")); // 拦截所有请求 // 设置Filter的初始化参数 Map<String, String> initParams = new HashMap<>(); initParams.put("exclusions", "*.js, *.css, /druid/*"); // 设置不拦截的请求 bean.setInitParameters(initParams); return bean; }
使用注解配置
Servlet:
@SuppressWarnings("serial") @WebServlet(urlPatterns = "/druid/*", initParams={ @WebInitParam(name="allow",value="192.168.16.110,127.0.0.1"),// IP白名单 (没有配置或者为空,则允许所有访问) @WebInitParam(name="deny",value="192.168.16.111"),// IP黑名单 (存在共同时,deny优先于allow) @WebInitParam(name="loginUsername",value="shanhy"),// 用户名 @WebInitParam(name="loginPassword",value="shanhypwd"),// 密码 @WebInitParam(name="resetEnable",value="false")// 禁用HTML页面上的“Reset All”功能 }) public class DruidStatViewServlet extends StatViewServlet { }
Filter:
@WebFilter(filterName="druidWebStatFilter",urlPatterns="/*", initParams={ @WebInitParam(name="exclusions",value="*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// 忽略资源 }) public class DruidStatFilter extends WebStatFilter { }
整合MyBatis
准备工作
勾选MyBatis
开发步骤:
- 配置Druid数据源以及相关属性
- 创建数据库表
- 创建对应的javaBean
注解版MyBatis
首先写一个用于曾删改查的Mapper接口
@Mapper // 指定这是一个操作数据库的mapper public interface DepartmentMapper { @Select("SELECT * FROM department WHERE id = #{id}") Department getDepartmentById(Integer id); @Delete("DELETE FROM department WHERE id = #{id}") int deleteDepartmentById(Integer id); @Options(useGeneratedKeys = true, keyProperty = "id") // 使用自动生成的主键,而且指定主键是department的id @Insert("INSERT INTO department(departmentName) VALUES(#{departmentName})") int insertDept(Department department); @Update("UPDATE department SET departmentName = #{departmentName} WHERE id = #{id}") int updateDept(Department department); }
注意:以后可能会遇到Mapper类非常多的情况,如果不想在每个类上都标注@Mapper,那么可以在SpringBoot的启动类上或者我们自定义的MyBatis配置类上标注上@MapperScan注解,并且填上要扫描的mapper包即可。
即@MapperScan(value = "com.jinxin.springbootmybatis.mapper")
@MapperScan(value = "com.jinxin.springbootmybatis.mapper") @SpringBootApplication public class SpringBootMybatisApplication { public static void main(String[] args) { SpringApplication.run(SpringBootMybatisApplication.class, args); } }
在Controller中进行使用
@RestController public class DeptController { @Autowired DepartmentMapper departmentMapper; @GetMapping("/dept/{id}") public Department getDepartment(@PathVariable("id") Integer id){ return departmentMapper.getDepartmentById(id); } @GetMapping("/dept") public Department insertDept(Department department){ departmentMapper.insertDept(department); return department; } }
自定义MyBatis的配置
在SpringBoot中将配置文件都替换成了配置类,因此可以使用配置类给MyBatis配置,方法就是给容器中添加一个ConfigurationCustomizer
@Configuration public class MyBatisConfig { @Bean public ConfigurationCustomizer configurationCustomizer(){ return new ConfigurationCustomizer() { @Override public void customize(org.apache.ibatis.session.Configuration configuration) { configuration.setMapUnderscoreToCamelCase(true); // 开启驼峰命名,即在javaBean中的lastName跟数据库列的last_name能够匹配的上 } }; } }
除了在配置类中配置以外,还可以在application.yaml文件中配置
mybatis: configuration: map-underscore-to-camel-case: true
配置版MyBatis
Mapper接口
同注解版一样,先准备一个接口,标注@Mapper注解,书写增删改查方法
@Mapper public interface EmployeeMapper { Employee getEmp(Integer id); void insertEmp(Employee employee); }
准备配置文件
准备MyBatis全局配置文件跟sql映射文件
全局配置文件:
<?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> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> </configuration>
SQL映射文件:
<?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.jinxin.springbootmybatis.mapper.EmployeeMapper"> <!-- Employee getEmp(Integer id); void insertEmp(Employee employee); --> <select id="getEmp" resultType="com.jinxin.springbootmybatis.bean.Employee"> SELECT * FROM employee WHERE id= #{id} </select> <insert id="insertEmp"> INSERT INTO employee(lastName, email, gender, d_id) VALUES (#{lastName}, #{email}, #{gender}, #{dId}) </insert> </mapper>
指定配置文件
在yaml文件中指定全局配置文件跟SQL映射文件的位置
mybatis: config-location: classpath:mybatis/mybatis-config.xml # 全局配置文件位置 mapper-locations: classpath:mybatis/mapper/*.xml # 指定sql映射配置文件的位置
在Controller中使用
@Autowired EmployeeMapper employeeMapper; @GetMapping("/emp/{id}") public Employee getEmp(@PathVariable("id") Integer id){ return employeeMapper.getEmp(id); }
整合SpringData的JPA
编写实体类
编写实体类和数据表进行映射,并配置好映射关系
// 使用JPA注解配置映射关系 @Entity // 告诉JPA这是一个实体类 @Table(name = "jpa_user") // 指定和哪个数据表对应,如果省略那默认表名就是类名小写 public class User { @Id // 这是一个主键 @GeneratedValue(strategy = GenerationType.IDENTITY) // 主键生成策略 private Integer id; @Column(name = "last_name", length = 50) // 这是和数据表对应的一个列,name是列名 private String lastName; @Column // 列名不写就默认是属性名 private String email; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
编写Dao操作实体类
编写一个Dao接口来操作实体类对应的数据表(Repository),继承JpaRepository类
// JpaRepository的两个泛型:一个是要操作的实体类,另一个是这个实体类中主键的类型 public interface UserRepository extends JpaRepository<User, Integer> { }
基本配置
在yaml文件中做好相应的配置
spring: jpa: hibernate: # 更新或者创建数据表 ddl-auto: update # 在控制台显示SQL show-sql: true
在controller中进行操作
由于JpaRepository中已经定义了许多方法,所以在UserRepository中可以直接使用
@RestController public class UserController { @Autowired private UserRepository userRepository; @GetMapping("/user/{id}") public Optional<User> getUser(@PathVariable("id") Integer id){ Optional<User> user = userRepository.findById(id); return user; } @GetMapping("/user") public User insertUser(User user){ User returnUser = userRepository.save(user); return returnUser; } }