目录(?)[+]
spring Boot构建的Web应用中,基于MySQL数据库的几种数据库连接方式进行介绍。
包括JDBC、JPA、MyBatis、多数据源和事务。
Spring Boot的Web应用中使用Mysq数据库,也充分展示Spring Boot的优势(尽可能少的代码和配置)。数据访问层我们将使用Spring Data JPA和hibernate(JPA的实现之一)。
注意:如果你想JDBC和JPA可以一起使用,Spring Boot 是支持的,你只需要把JDBC和JPA的依赖都添加在pom.xml 中即可。无需其他特殊处理。
要使用MySQL,需要引入对应的connector,因此,首先在pom文件中添加如下依赖:
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependencies> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-webartifactId> dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-data-jpaartifactId> dependency> <dependency> <groupId>mysqlgroupId> <artifactId>mysql-connector-javaartifactId> dependency> dependencies>
在src/main/resources/application.properties中设置数据源和jpa配置。
spring.datasource.url = jdbc:mysql://localhost:3306/test
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driverClassName = com.mysql.jdbc.Driver
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = update
# Naming strategy
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
# stripped before adding them to the entity manager)
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
全部的配置都在如上的文件中了,不需要另外的XML配置和Java配置。
上文中的数据库配置,你需要换成你的数据库的地址和用户名密码。
hibernate的ddl-auto=update配置表名,数据库的表和列会自动创建(根据Java实体的熟悉), 这里 可以看到更多得hibernate配置。
spring.jpa.hibernate.ddl-auto=create-drop
。
spring.jpa.show-sql = true
来显示自动创建表的SQL语句,通过
spring.jpa.database = MYSQL
指定具体的数据,如果不明确指定Spring boot会根据classpath中的依赖项自动配置。
在Spring项目中,如果数据比较简单,我们可以考虑使用JdbcTemplate,而不是直接定义Datasource,配置jdbc的代码如下:
@Autowired
private JdbcTemplate jdbcTemplate;
只要定义了上面这个代码,Spring Boot会自动创建一个Datasource对象,然后再创建一个jdbctemplate对象来管理datasource,通过jdbctemplate操作数据库可以减少大量模板代码。如果你对SpringBoot的原理感兴趣,可以在org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration类中查看其具体实现。
package com.city.data.domain;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
@Table(name = "city")
public class City implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private int cityId;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private int provinceId;
public City() {
}
public City( int cityId) {
super();
this.cityId = cityId;
}
public int getCityId() {
return cityId;
}
public void setCityId(int id) {
this.cityId = id;
}
......
}
package com.city.data.service;
/**
*DAO层
*/
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
import com.city.data.domain.City;
interface CityRepository extends Repository {
City findByName(String name);
}
我们都没有写一行SQL语句,也没有在代码中涉及到数据库连接、建立查询等方面的内容。只有实体类上的各种注解表明我们在于数据库做交互:@Entity,@Repository,@Id,@GeneratedValue,@ManyToOne,@ManyToMany以及@OneToMany,这些注解属于JavaPersistance API。我们通过Respository接口的子接口与数据库交互,同时由Spring建立对象与数据库表、数据库表中的数据之间的映射关系。下面依次说明这些注解的含义和使用:
@Table(name = "books")
即可。需要特别注意,每个Entity类都应该有一个protected访问级别的无参构造函数,用于给Hibernate提供初始化的入口。
package com.city.data.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.city.data.domain.City;
@Component("cityService")
@Transactional
public class CityServiceImpl implements CityService {
private final CityRepository cityRepository;
@Autowired
public CityServiceImpl(CityRepository cityRepository) {
this.cityRepository = cityRepository;
}
//@Override
public City getCity(String cityName) {
Assert.notNull(cityName, "Name must not be null");
return this.cityRepository.findByName(cityName);
}
}
新建一个查询控制器CityController,
package com.city.data.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.*;
import com.city.data.service.CityService;
import com.city.data.domain.City;;
//原始格式
//@Controller
//json格式
@RestController
public class CityController {
@Autowired
private CityService cityService;
@RequestMapping("/")
@ResponseBody
@Transactional(readOnly = true)
public int getBeijing() {
//return "helloWorld";
return this.cityService.getCity("beijing").getCityId();
}
/**
* @PathVariable是用来获得请求url中的动态参数的
* @param name
* @return
*/
@RequestMapping(value = "/{name}", method = RequestMethod.GET)
public Map getCity( @PathVariable String name) {
City city = this.cityService.getCity(name);
Map response = new LinkedHashMap<>();
response.put("msg", "get city with name(" + name +")");
response.put("city", city);
return response;
}
}
你可以使用浏览器访问url http://127.0.0.1:8080
1、属性配置文件(application.properties)
如果使用JNDI,则可以替代 spring.datasource 的 url、username、password,如:
值得一提的是,无论是Spring Boot默认的DataSource配置还是你自己的DataSource bean,都会引用到外部属性文件中的属性配置。所以假设你自定义的DataSource bean,你可以在定义bean时设置属性,也可以在属性文件中,以“spring.datasource.*”的方式使属性配置外部化。
2、pom.xml 配置maven依赖
3、Java代码范例
CityServiceImpl.java
注意,使用jdbc要有变量
@Autowired
private JdbcTemplate jdbcTemplate;
"code" class="java">/*
/*
*/
package com.city.data.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import com.city.data.domain.City;
import com.city.data.common.JdbcSQL;
@Component("cityService")
@Transactional
public class CityServiceImpl implements CityService {
private final CityRepository cityRepository;
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
public CityServiceImpl(CityRepository cityRepository) {
this.cityRepository = cityRepository;
}
/**
*
*/
public List getCityList(CitySearchCriteria criteria){
String sql = "SELECT * FROM city";
String cityName = criteria.getName();
int provinceid = criteria.getProvinceId();
String where = "";
if(provinceid > 0 ) {
where += " province_id=" + provinceid;
}
if(StringUtils.hasLength(cityName) ) {
where += " name=" + cityName;
}
if(!where.isEmpty() ) {
sql =sql + " where " + where;
}
return (List) jdbcTemplate.query(sql, new RowMapper(){
@Override
public City mapRow(ResultSet rs, int rowNum) throws SQLException {
City city = new City();
city.setCityId(rs.getInt("city_id"));
city.setName(rs.getString("name"));
city.setMap(rs.getString("map"));
city.setProvinceId(rs.getInt("province_id"));
return city;
}
});
}
public List getCityList2(Map condition){
JdbcSQL jdbcSQL =new JdbcSQL();
jdbcSQL.setTable("city");
jdbcSQL.setConditon(condition);
return jdbcSQL.selectByCondition();
}
public List
然后启动项目,访问地址: http://localhost:8080/
Tomcat7之前,Tomcat本质应用了DBCP连接池技术来实现的JDBC数据源,但在Tomcat7之后,Tomcat提供了新的JDBC连接池方案,作为DBCP的替换或备选方案,解决了许多之前使用DBCP的不利之处,并提高了性能。详细请参考:http://wiki.jikexueyuan.com/project/tomcat/tomcat-jdbc-pool.html
Spring Boot为我们准备了最佳的数据库连接池方案,只需要在属性文件(例如application.properties)中配置需要的连接池参数即可。
我们使用Tomcat数据源连接池,需要依赖tomcat-jdbc,只要应用中添加了spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa依赖,则无需担心这点,因为将会自动添加 tomcat-jdbc 依赖。
假如我们想用其他方式的连接池技术,只要配置自己的DataSource bean,即可覆盖Spring Boot的自动配置。
请看我的数据源配置:
配置过连接池的开发人员对这些属性的意义都有所认识。
我们打开DEBUG日志输出,logback.xml 中添加:
然后启动项目,注意观察日志输出,如下图中会显示自动启用了连接池:
我在上面的数据源配置中添加了过滤器,并设置了延迟时间为0(故意设置很低,实际项目中请修改):
这个时候,我们访问 http://localhost:8080/myspringboot/stu/list 观察日志,会发现框架自动将大于该时间的数据查询进行警告输出,如下:
问题:
1、连接池的连接在最大生存时间 时间内没有请求数据库,再次使用的连接就报错。
spring.datasource.max-lifetime=86400000 (单位 毫秒)
2、如果连接池的连接长时间不使用(可能时间短于max-lifetime),但是超过mysql的wait_timeout的时间,mysql也会进行回收这个连接的。
my.cnf
wait_timeout=31536000
interactive_timeout=31536000
Mysql服务器默认的“wait_timeout”是8小时【也就是默认的值默认是28800秒】,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection,通俗的讲就是一个连接在8小时内没有活动,就会自动断开该连接。 wait timeout的值可以设定,但最多只能是2147483,不能再大了。也就是约24.85天 .