目录
一、整合JDBC相关配置
pom.xml配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
application.yml配置
spring:
datasource:
#mysql驱动8.0及以上版本,要使用com.mysql.cj.jdbc.Driver驱动类
driver-class-name: com.mysql.cj.jdbc.Driver
#mysql驱动8.0及以上版本,url后面要加上时区,GMT%2B8表示中国时区,不然报时区错误
url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8
username: root
password: 123
连接测试
@SpringBootTest
class SpringBoot05JdbcApplicationTests {
@Autowired
DataSource dataSource;
@Test
void contextLoads() throws SQLException {
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
}
运行结果:
- SpringBoot 默认采用的数据源连接池是: com.zaxxer.hikari.HikariDataSource
- 数据源相关配置都在 DataSourceProperties 中。
二、Druid连接池与监控管理
自定义配置数据源连接池
1.pom.xml引入Druid依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
2.application.yml配置数据源
spring:
datasource:
#mysql驱动8.0及以上版本,要使用com.mysql.cj.jdbc.Driver驱动类
driver-class-name: com.mysql.cj.jdbc.Driver
#mysql驱动8.0及以上版本,url后面要加上时区,GMT%2B8表示中国时区,不然报时区错误
url: jdbc:mysql://127.0.0.1:3306/bill?serverTimezone=GMT%2B8
username: root
password: 123
#指定druid数据源
type: com.alibaba.druid.pool.DruidDataSource
#数据源其他配置, DataSourceProperties中没有相关属性,需要手动配置
initialSize: 8
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,logback
maxPoolPreparedStatementPerConnectionSize: 25
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
3.通过配置类,将配置中的数据和DruidDatasource绑定
@Configuration
public class DruidfConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")//绑定数据源配置
public DataSource druid(){
return new DruidDataSource();
}
}
配置Druid监控
@Configuration
public class DruidfConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")//绑定数据源配置
public DataSource druid(){
return new DruidDataSource();
}
//配置Druid监控
//1.配置一个管理后台的Servlet
@Bean
public ServletRegistrationBean statViewServlet(){
//请求路径以 /druid/ 开头都会去访问这个Servlet
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(),"/druid/*");
//配置初始化参数
Map<String,String> initParam = new HashMap<>();
//访问的用户名密码
initParam.put(StatViewServlet.PARAM_NAME_USERNAME,"root");
initParam.put(StatViewServlet.PARAM_NAME_PASSWORD,"123");
//允许访问的ip,默认所有ip访问
initParam.put(StatViewServlet.PARAM_NAME_ALLOW,"");
//禁止访问的ip
initParam.put(StatViewServlet.PARAM_NAME_DENY,"192.168.11.1");
bean.setInitParameters(initParam);
return bean;
}
//2.配置一个监控的filter
@Bean
public FilterRegistrationBean filter(){
FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
bean.setFilter(new WebStatFilter());
//配置初始化参数
Map<String,String> initParam = new HashMap<>();
//排除请求
initParam.put(WebStatFilter.PARAM_NAME_EXCLUSIONS,"*.js,*.css,/druid/*");
//拦截所有的请求
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
登录druid监控系统
三、整合MyBatis
创建项目时勾选mybatis框架
添加mybatis依赖
<!--导入mybatis启动器-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
mybatis使用注解方式
1.创建实体类和mapper接口
//指定这是操作数据的Mapper,或使用在配置类使用@MapperScan(mapper包名)注解扫描
@Mapper
public interface ProviderMapper {
/**
* useGeneratedKeys:是否使用主键自增长
* keyProperty:对应实体类中主键的属性
*/
@Options(useGeneratedKeys = true, keyProperty = "pid")
@Insert("insert into provider(providerName)values(#{providerName})")
int addProvider(Provider provider);
@Delete("delete from provider where pid=#{pid}")
int deleteProvide(Integer pid);
@Update("update provider set providerName=#{providerName} where pid=#{pid}")
int updateProvider(Provider provider);
@Select("select * from provider where pid=#{pid}")
Provider getProvider(Integer pid);
}
2.使用驼峰命名方式,把数据库字段如:provider_name自动转成providerName
@Configuration
public class MybatisConfig {
@Bean
public ConfigurationCustomizer configurationCustomizer(){
return new ConfigurationCustomizer() {
@Override
public void customize(org.apache.ibatis.session.Configuration configuration) {
//开启驼峰命名方式
configuration.setMapUnderscoreToCamelCase(true);
}
};
}
}
3.添加Controller测试
@Controller
public class ProviderController {
@Autowired
private ProviderMapper providerMapper;
@ResponseBody
@GetMapping("/provider/{pid}")
public Provider getProvider(@PathVariable("pid")Integer pid){
Provider provider = providerMapper.getProvider(pid);
return provider;
}
@GetMapping("/add")
public Provider addProvider(Provider provider){
System.out.println(provider);
providerMapper.addProvider(provider);
return provider;
}
}
使用xml配置文件
1.mapper接口
@Mapper
public interface BillMapper {
Bill getBill(Integer bid);
int getBill(Bill bill);
}
2.在resources目录下创建mybatis核心配置文件和mapper映射文件
MybatisConfig.xml
<?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>
<!--mybatis核心配置-->
<settings>
<!--开启驼峰命名-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
映射文件
<?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.mxg.springboot.mapper.BillMapper">
<select id="getBill" resultType="com.mxg.springboot.entities.Bill" >
select * from bill where bid=#{bid}
</select>
<insert id="addBill" parameterType="com.mxg.springboot.entities.Bill">
insert into bill(bill_code,bill_name)values(#{billCode},#{billName})
</insert>
</mapper>
3.application.yml指定mybatis配置文件路径
mybatis:
#核心配置文件路径
config-location: classpath:mybatis/MybatisConfig.xml
#映射配置文件路径
mapper-locations: classpath:mybatis/mapper/*.xml
4.添加Controller测试
@Controller
public class BillController {
@Autowired
private BillMapper billMapper;
@ResponseBody
@GetMapping("/bill/{bid}")
public Bill getBill(@PathVariable("bid") Integer bid){
return billMapper.getBill(bid);
}
@GetMapping("/bill")
public Bill addBill(Bill bill){
billMapper.addBill(bill);
return bill;
}
}
四、整合SpringDataJPA
JPA
的底层遵守是
ORM(
对象关系映射
)
规范,因此
JPA
其实也就是
java
实体对象和关系型数据库建立起映射关系,通过面向对象编程的思想操作关系型数据库的规范
1. 在application全局配置文件配置JPA
spring:
datasource:
#mysql驱动8.0及以上版本,要使用com.mysql.cj.jdbc.Driver驱动类
driver-class-name: com.mysql.cj.jdbc.Driver
#mysql驱动8.0及以上版本,url后面要加上时区,GMT%2B8表示中国时区,不然报时区错误
url: jdbc:mysql://127.0.0.1:3306/jpa?serverTimezone=GMT%2B8
username: root
password: 123
#Jpa相关配置sping.jpa.*
jpa:
#控制台显示SQL
show-sql: true
hibernate:
#会根据映射实体类自动创建或更新数据表
ddl-auto: update #update:创建和更新 create:只创建
#默认创建表类型是MyISAM,是非事务安全的,所以无法实现事务回滚
#指定如下:创建的表类型是Innodb,才可以进行对事务的回滚
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
2.
创建实体类,并使用
JPA
注解进行配置映射关系
//使用JPA注解进行配置映射关系
@Entity //说明它是和数据表映射的类
@Table(name = "tb_user")//指定对应映射的表名,省略默认表名就是类名
public class User {
@Id //标识为主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//标识主键自增长
private Integer id;
//指定对应数据表的列的字段名,length限制最大长度为5
@Column(name = "user_name", length = 5)
private String username;
//默认表的字段名和属性名一样
@Column
private String password;
//指定数据库生成时间方式(类型TemporalType.TIMESTAMP:日期+时间)
@Temporal(TemporalType.TIMESTAMP)
private Date createTime;
//省略get/set方法
}
3. 创建 UserRepository 接口继承 JpaRepository
/**
* 自定义接口继承JpaRepository,就有crud及分页等基本功能
*/
public interface UserRepository extends JpaRepository<User, Integer> { //指定的泛型<操作的实体类,主键类型>
}
4. 添加controller测试
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/user/{id}")
public User getUserById(@PathVariable("id") Integer id){
Optional<User> user = userRepository.findById(id);
return user.get();
}
@GetMapping("/user")
public User addUser(User user){
return userRepository.save(user);
}
}
五、Springboot事务管理
在
Spring Boot
中,当我们使用了
spring-boot-starter-jdbc
或
spring-boot-starter-data-jpa依赖的时候,框架会自动默认分别注入
DataSourceTransactionManager
或
JpaTransactionManager。所以我们不需要任何额外配置就可以用
@Transactional
注解进行事务的使用
注意:Hibernate创建数据库表时
- 默认创建表类型是MyISAM,是非事务安全的,所以无法实现事物回滚; Innodb才可以进行对事物的回滚
- (具体在上面整合JPA第3步)需要指定spring.jpa.database-platform=org.hibernate.dialect.MySQL57Dialect
1.在启动类上,使用@EnableTransactionManagement开启注解方式事务支持
@EnableTransactionManagement
@SpringBootApplication
public class SpringBootJpaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootJpaApplication.class, args);
}
}
2.在Service层添加@Transactional注解进行事务管理
@Service
public class AccountServiceImpl implements IAccountService {
@Autowired
private AccoutRepository accoutRepository;
@Transactional//事务管理注解
@Override
public Boolean transfer(Account from, Account to, double money) {
from.setMoney(from.getMoney() - money);
accoutRepository.save(from);
int a = 1/0;//模拟错误
to.setMoney(to.getMoney() + money);
accoutRepository.save(to);
return true;
}
}
六、事务的隔离级别和传播行为
隔离问题:
- 脏读:A事务执行过程中修改了id=1的数据,未提交前,B事务读取了A修改的id=1的数据,而A事务却回滚了,这样B事务就形成了脏读
- 不可重复读:A事务先读取了一条数据,然后执行逻辑的时候,B事务将这条数据改变了,然后A事务再次读取的时
候,发现数据不匹配了,就是所谓的不可重复读了 - 幻读:A事务先根据条件查询到了N条数据,然后B事务新增了M条符合A事务查询条件的数据,导致A事务再次查询
发现有N+M条数据了,就产生了幻读
隔离级别:
- SERIALIZABLE(串行化):能解决3种读问题,非并发访问,性能最差
- READ_COMMITTED(读已提交数据):表示一个事务只能读取已提交的数据,可防止脏读(一般用这个)
- REPEATABLE_READ(可重复读):表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。可以防止脏读和不可重复读
- READ_UNCOMMITTED(读未提交数据):不做任何处理,可能出现任何事务并发问题
- ISOLATION_DEFAULT:用底层数据库的设置隔离级别,数据库设置的是什么我就用什么;
指定方式:通过isolation属性设置
@Transactional(isolation = Isolation.READ_COMMITTED)
传播行为:
- REQUIRED :(默认)如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
- SUPPORTS :如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
- MANDATORY :如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
- REQUIRES_NEW :创建一个新的事务,如果当前存在事务,则把当前事务挂起。
- NOT_SUPPORTED :以非事务方式运行,如果当前存在事务,则把当前事务挂起。
- NEVER :以非事务方式运行,如果当前存在事务,则抛出异常。
- NESTED :如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 REQUIRED
指定方式:通过propagation属性设置
@Transactional(propagation = Propagation.REQUIRED)