Jdbc Template超简单上手
啥是jdbcTemplate
前几天写到了Spring的一些理论,今天想到了Spring里封装的jdbcTemplate,所以写了这篇博客,spring里的jdbcTemplate做了深层次的封装,使用了spring的注入功能,可以把DataSource注册道JdbcTemplate里。结尾还穿插了一点Spring事务的概念。
这里还使用了druid,它是阿里巴巴的数据源(数据库连接池),集合了c3p0、dbcp、proxool等连接池的优点,还加入了日志监控,有效的监控DB池连接和SQL的执行情况。
DRUID的DataSource类为:com.alibaba.druid.pool.DruidDataSource。
其他配置参数如下:
为什么要使用数据库连接池呢,首先我们要了解
数据库连接池的重要性
1、普通的JDBC连接数据库每次向数据库建立连接的时候都将connection加载到内存,再验证用户名等信息,这样会消耗一定的时间,每次的数据库连接,使用完后再断开,这样的方式会消耗大量的资源和时间。同时上千人访问的话将占用很多系统资源,导致服务器崩溃
2、数据库连接池其实就是一个为数据库连接建立的一个“缓存池”,预先在数据库连接池中放入一定数量的连接。当需要数据库连接时,从连接池中拿就是了,用完再放回。数据库连接池负责分配、管理、释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立
3、数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中(initialPoolSize).无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量
4、连接池的最大数据库连接数量限定了这个连接池占有的最大连接数(maxPoolSize)。当应用程序向连接池请求的连接数超过最大连接数时,这些请求将加入到等待队列中
5、数据库连接池相对于无连接池的优点
- 资源重用,避免频繁创建
- 更快的系统反应速度
- 实现某一应用最大可用数据库连接数的限制避免某一应用独占所有的数据库资源
- 统一的连接管理,避免数据库连接泄露
6、常用的数据库连接池
- c3p0(常用)
- dbcp
- proxool
下面是实操
使用前我们要导入几个包
pom.xml
<!--jdbcTemplate相关依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!--mysql 数据库驱动-->
<!-- Mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.14</version>
</dependency>
<!--这个junit是测试@Test用的-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--这里我想在实体类里偷个懒所以用了lombok,这个可有可无,没带的话实体类正常写getset有参无参构造即可-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.feng"></context:component-scan>
<!--引入外部的配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置数据库连接-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="${prop.url}"></property>
<property name="username" value="${prop.userName}"></property>
<property name="password" value="${prop.password}"></property>
<property name="driverClassName" value="${prop.driverClass}"></property>
</bean>
<!--JdbcTemplate对象创建,注入dataSource对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入dataSource对象-->
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
User.java(如果没有导入lombok依赖,这里正常写getset有参无参构造即可)
package com.feng.entiy;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* <h3>spring-study</h3>
* <p></p>
*
* @author : Nicer_feng
* @date : 2020-09-17 15:48
**/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
private Integer id;
private String user_name;
private Integer status;
}
test类
增删改查直接来
import com.feng.entiy.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.List;
/**
* <h3>spring-study</h3>
* <p></p>
*
* @author : Nicer_feng
* @date : 2020-09-17 15:25
**/
public class testSpring {
private JdbcTemplate jdbcTemplate;
private ApplicationContext context = null;
//初始化连接池
{
context = new ClassPathXmlApplicationContext("applicationContext.xml");
jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");
}
//测试是否连接数据库
@Test
public void testIsConnect() throws SQLException {
DataSource dataSource = context.getBean(DataSource.class);
System.out.println("连接成功"+dataSource.getConnection());
}
@Test
public void insert(){
String sql = "insert into t_user values (?,?,?)";
int liu = jdbcTemplate.update(sql, 2, "liu", 2);
}
@Test
public void update(){
String sql = "update t_user set user_name=? where id =?";
jdbcTemplate.update(sql,"liu66",2);
}
@Test
public void delete(){
String sql = "delete from t_user where id =?";
jdbcTemplate.update(sql,2);
}
@Test
public void query(){
String sql = "select * from t_user where id =?";
RowMapper<User> mapper = new BeanPropertyRowMapper<>(User.class);
List<User> query = jdbcTemplate.query(sql, mapper, 1);
System.out.println(query.toString());
}
}
这里面用到一个RowMapper的对象
/*
*从数据库中获取一条记录,实际是得到对应的一个对象
*RowMapper:行的映射
*Spring 提供了一个便利的RowMapper实现-----BeanPropertyRowMapper
*它可自动将一行数据映射到指定类的实例中 它首先将这个类实例化,然后通过名称匹配的方式,映射到属性中去。
*字段 bean属性
*USER_NAME --> userName
*USER_ID --> userId
*/
查询结果
Spring事务
回顾事务
- 把一组业务当成一个业务来做;要么都成功,要么都失败
- 事务在项目开发中十分地重要,涉及到数据的一致性问题
- 要确保完整性和一致性
事务的ACID原则:
- 原子性
- 一致性
- 隔离性
- 多个业务可能操作同一个资源,防止数据损坏
- 持久性
- 事务一旦提交,无论系统发生什么问题,结果都不会被影响,被持久化地写到存储器中
事务的详细介绍还可以去我之前有关数据库的博客看看,详见
https://nicer.blog.csdn.net/article/details/108535197
spring中的事务管理
- 声明式事务:AOP
- 编程式事务:需要在代码中,进行事务的管理
在spring-dao中加入配置
<!--配置声明式事务,即事务管理器-->
<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--结合AOP实现事务的织入-->
<!--配置事务(通知/的类)-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<!--配置事务的传播特性:new propagation:传播 默认为:REQUIRED-->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="select" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.feng.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
为什么需要事务:
- 如果不配置事务,可能存在数据提交不一致的情况
- 如果我们不在spring中取配置声明式事务,我们就需要在代码中手动配置事务
- 事务在项目的开发中十分重要,涉及到数据的一致性和完整性
具体的事务实现可以见