在项目开发中,数据库的访问是必不可少的,对于数据访问层,无论是SQL还是NoSql,SpringBoot默认采用整合Spring Data的方式进行统一处理,添加了大量的自动配置,屏蔽了很多设置.引入各种Template或Repository来简化我们对数据访问层的操作,对我们来说只需要进行简单的设置即可.
我们先用IDEA创建一个SringBoot应用,引入web组件,jdbc组件
在SpringBoot的配置文件中配置好数据源,我们就可以查看默认的数据库连接:
spring.datasource.url = jdbc:mysql://127.0.0.1:3306/tale?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.username = root
spring.datasource.password = 123456
spring.datasource.driverClassName = com.mysql.jdbc.Driver
在测试类中测试连接:
@Autowired
DataSource dataSource;
@Test
public void contextLoads() throws SQLException {
System.out.println(dataSource.getClass());
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
可以看到控制台打印:
可以看到,SpringBoot2.0+使用的默认数据源是:com.zaxxer.hikari.HikariDataSource
它还支持以下数据源:dbcp2,tomcat
我们查看DataSourceConfiguration
这个类,可以看到它还支持自定义数据源:
abstract class DataSourceConfiguration {
DataSourceConfiguration() {
}
protected static <T> T createDataSource(DataSourceProperties properties, Class<? extends DataSource> type) {
return properties.initializeDataSourceBuilder().type(type).build();
}
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"}
)
static class Generic {
Generic() {
}
@Bean
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
@ConditionalOnClass({BasicDataSource.class})
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"},
havingValue = "org.apache.commons.dbcp2.BasicDataSource",
matchIfMissing = true
)
static class Dbcp2 {
Dbcp2() {
}
@Bean
@ConfigurationProperties(
prefix = "spring.datasource.dbcp2"
)
public BasicDataSource dataSource(DataSourceProperties properties) {
return (BasicDataSource)DataSourceConfiguration.createDataSource(properties, BasicDataSource.class);
}
}
@ConditionalOnClass({HikariDataSource.class})
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"},
havingValue = "com.zaxxer.hikari.HikariDataSource",
matchIfMissing = true
)
static class Hikari {
Hikari() {
}
@Bean
@ConfigurationProperties(
prefix = "spring.datasource.hikari"
)
public HikariDataSource dataSource(DataSourceProperties properties) {
HikariDataSource dataSource = (HikariDataSource)DataSourceConfiguration.createDataSource(properties, HikariDataSource.class);
if (StringUtils.hasText(properties.getName())) {
dataSource.setPoolName(properties.getName());
}
return dataSource;
}
}
@ConditionalOnClass({org.apache.tomcat.jdbc.pool.DataSource.class})
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"},
havingValue = "org.apache.tomcat.jdbc.pool.DataSource",
matchIfMissing = true
)
static class Tomcat {
Tomcat() {
}
@Bean
@ConfigurationProperties(
prefix = "spring.datasource.tomcat"
)
public org.apache.tomcat.jdbc.pool.DataSource dataSource(DataSourceProperties properties) {
org.apache.tomcat.jdbc.pool.DataSource dataSource = (org.apache.tomcat.jdbc.pool.DataSource)DataSourceConfiguration.createDataSource(properties, org.apache.tomcat.jdbc.pool.DataSource.class);
DatabaseDriver databaseDriver = DatabaseDriver.fromJdbcUrl(properties.determineUrl());
String validationQuery = databaseDriver.getValidationQuery();
if (validationQuery != null) {
dataSource.setTestOnBorrow(true);
dataSource.setValidationQuery(validationQuery);
}
return dataSource;
}
}
}
它的自定义数据源是这样定义的:
@ConditionalOnMissingBean({DataSource.class})
@ConditionalOnProperty(
name = {"spring.datasource.type"}
)
static class Generic {
Generic() {
}
@Bean
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
其次,我们可以将建表以及插入数据的sql脚本放在指定的目录,这样项目在启动的时候会自动建表:
默认情况下,将脚本命名为schema.sql
或者schema-all.sql
,并放在resource目录下就可以
如果要自己指定文件名,需要在配置文件中配置一个属性来指定文件名:
spring:
datasource:
schema:
‐ classpath:department.sql
//该属性的值是个列表,我们可以指定多个文件
//在SPringBoot2.0以后,如果要运行sql脚本 还需要加入下面这个配置
initialization-mode: always
SpringBoot默认整合了JdbcTemplate操作数据库,我们可以直接使用:
@Controller
public class HelloController {
@Autowired
private JdbcTemplate jdbcTemplate;
@ResponseBody
@RequestMapping("/map")
public Map<String, Object> map() {
List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from t_contents");
for (Map<String, Object> map : maps
) {
System.out.println(map);
}
return maps.get(0);
}
}
页面访问:
在日常的项目开发中,我们一般不会是用原生的JDBC来操作数据库,笔主经常遇到的就是我们阿里的Druid,在这里我们也来这个Druid到SpringBoot项目中.
引入pom依赖
首先在项目的pom.xml中引入Druid的坐标依赖,可以直接从maven仓库中搜索到.
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.10version>
dependency>
在application.yml或者properties文件中配置数据源
使用type属性来指定我们使用的数据源
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:3306/tale?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
type: com.alibaba.druid.pool.DruidDataSource
除了这些参数,Druid还提供了很多的属性配置:
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
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
当然,如果直接在配置文件中引入这些是不行的,因为默认的属性不会绑定这些参数,我们需要自定定义一个DataSource来绑定参数,可如下操作:
/**
* 配置Driud数据源
*/
@Configuration
public class DruidConfig {
@Bean
//下面的注解表示将属性文件中前缀是spring.datasource的属性绑定到当前数据源
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource druid() {
return new DruidDataSource();
}
/**
* druid的强大在于有一套完整的监控配置,我们可以在这里配置一下,配置druid的后台监控需要配置
* 一个servlet,我们可以直接使用servletRegistrationBean来配置,配置的servlet的名称
* 是statViewServlet,
*/
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean bean
= new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
//可以在这个servlet中设置参数来定义后台的一些参数
Map<String, String> initParms = new HashMap<>();
//配置登录用户名
initParms.put("loginUsername", "admin");
//配置密码
initParms.put("loginPassword", "123456");
//配置访问权限,默认是所有都能访问
initParms.put("allow", "");
//配置拒绝访问的ip
initParms.put("deny", "");
bean.setInitParameters(initParms);
return bean;
}
/**
* 要使用druid的后台监控功能,还可以配置一个filter,它的名称是webStatFilter
*
*/
@Bean
public FilterRegistrationBean webStatFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String, String> initParms = new HashMap<>();
//不拦截的资源
initParms.put("exclusions", "*.js,*.css,/druid/*");
bean.setInitParameters(initParms);
//要拦截的请求
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
启动项目,访问localhost:8080/druid
,就可以直接跳转到登录页面,使用我们在servlet中配置的账号登录就可以登录Druid的后台了:
使用注解整合Mybatis
首先引入mybatis的maven坐标:
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>1.3.1version>
dependency>
创建对应的javeBean和Mapper:
public class User {
private int id;
private String userName;
//省略set,get
}
/**
* 用户表对应的mapper
*/
@Mapper
//mapper注解指定这个接口是mybatis的mapper,且将此接口加入容器
public interface UserMapper {
/**
* 通过id查询user对象
* @param id 主键
* @return user对象
*/
@Select("select * from user where id=#{id}")
User queryUserById(int id);
@Options(useGeneratedKeys = true, keyProperty = "id")
//options用来定义主键返回,keyProperty指定主键对应的属性
@Insert("insert into user (userName) values (#{userName})")
int insert(User user);
}
在controller层定义好对应的映射:
@GetMapping("/user/{id}")
@ResponseBody
public User queryUser(@PathVariable("id") int id) {
User user = userMapper.queryUserById(id);
return user;
}
@GetMapping("/user")
@ResponseBody
public User insertUser(User user) {
userMapper.insert(user);
return user;
}
如上做完以后就可以访问页面了,如果需要配置数据库映射的时候使用驼峰命名的规则,可以自定义一个配置规则:
@org.springframework.context.annotation.Configuration
public class MyBatisConfig {
@Bean
public ConfigurationCustomizer configurationCustomizer(){
return new ConfigurationCustomizer(){
@Override
public void customize(Configuration configuration) {
configuration.setMapUnderscoreToCamelCase(true);
}
};
}
}
如果我们的Mapper文件太多,不想一个个写@Mapper
注解,也可以直接在启动类上使用以下方式来扫描包路径下的所有mapper:
@SpringBootApplication
@MapperScan(value = "mapper文件所在的包路径, ex:com.xiaojian.mapper")
public class SpringbootJdbcApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootJdbcApplication.class, args);
}
}
使用配置文件整合Mybatis
使用配置文件来整合Mybatis也很简单,只需要将sql定义在xml文件中即可,再写Mybatis的核心配置文件就可以,我们可以在SpringBoot的配置文件中指定Mybatis的配置文件和Mapper映射文件的位置:
mybatis:
config‐location: classpath:mybatis/mybatis‐config.xml 指定全局配置文件的位置
mapper‐locations: classpath:mybatis/mapper/*.xml 指定sql映射文件的位置
引入jpa相关的pom依赖
编写一个实体类和数据库中的表对应
//使用JPA注解配置映射关系
@Entity //告诉JPA这是一个实体类(和数据表映射的类)
@Table(name = "tbl_user") //@Table来指定和哪个数据表对应;如果省略默认表名就是user;
public class User {
@Id //这是一个主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//自增主键
private Integer id;
@Column(name = "last_name",length = 50) //这是和数据表对应的一个列
private String lastName;
@Column //省略默认列名就是属性名
private String email;
编写一个xxxRepository接口来操作对应的表
//继承JpaRepository来完成对数据库的操作,JpaRepository继承了CrudRepository和Page类的功能,既可以进行正常的增删改查,也可以进行分页
public interface UserRepository extends JpaRepository<User,Integer> {
}
还需要在配置文件中配置:
spring:
jpa:
hibernate:
# 更新或者创建数据表结构
ddl‐auto: update
# 控制台显示SQL
show‐sql: true
完成以上配置以后就可以在controller层写对应的方法来操作数据.
SpringBoot对数据访问的问题就记录这些,在实际的运用中,还有一些高级的功能没有说到,以后会逐渐补充~~