事务
把一组业务当成一个业务来做;要么都成功,要么都失败,保证业务操作完整性的一种数据库机制。
事务四大特性(ACID)
-
原子性(Atomicity)
在一个事务中,所有的操作要么都提交成功,要么都失败回滚。
-
一致性(Consistency)
在一组业务操作下,必须保证前后关联数据的一致性
-
隔离性(Isolation)
在事务并发的情况下,事务之间是隔离的,一个事务不能影响其他事务的运行(完全的隔离是不现实的,严重影响性能)
-
持久性(Durability
事务操作完成,数据更改持久化到数据库中,是持久性的
同一时间,多个线程同时处理造成并发所产生的的问题
-
脏读
事务A读取事务B更新的数据,但事务B回滚了,事务A读取的为脏数据
user{id:1, balance:200}
事务A begin 事务B begin update user set balance=100 where id=1;
#balance=100select balance from user where id=1;
#balance=100rollback(); //回滚
#balance=200 -
不可重复读
事务A读取同一数据两次,在两次之间事务B对数据做了修改,导致事务A前后读取数据不一致
事务A begin 事务B begin select balance from user where id=1;
#balance=200update user set balance=100 where id=1;
#balance=100select balance from user where id=1;
#balance=100 -
幻影读
事务A两次对表读取,由于其他事务操作导致最终数据不一致
与不可重复读的区别(不可重复读是行级,幻影读是表级)事务A begin 事务B begin select count(*) count from user ;
#count=1insert into user values(2, 500);
commit;select count(*) count from user ;
#count=2
JdbcTemplate使用
1. 在AOP的基础上加上pom依赖,创建Spring maven项目
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.2.19.RELEASE</version>
</dependency>
spring-orm自身依赖spring-jdbc(数据库连接)和spring-tx(transaction事务管理)
2. 配置Druid连接池
<context:property-placeholder location="db.properties"/>
<bean class="com.alibaba.druid.pool.DruidDataSource" name="dataSource">
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${password}"/>
<property name="url" value="${url}"/>
<property name="driverClassName" value="${driverClassName}"/>
</bean>
测试一下
@Test
public void testDruid() {
DruidDataSource dataSource = context.getBean(DruidDataSource.class);
System.out.println(dataSource);
}
Test:
3. 配置JdbcTemplate
<!--引入JdbcTemplate bean组件-->
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
获取JdbcTemplate对象
@Test
public void testJdbcTemplate() {
JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
System.out.println(jdbcTemplate);
}
Test:
4. 数据库创建一张user表并初始化数据,查询表数据总条数(查询单值)
使用JdbcTemplate方法获取
/**
* @Description: 查询单个值
*/
@Test
public void testSingle() {
JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
Long count = jdbcTemplate.queryForObject("select count(*) from t_user", Long.class);
System.out.println("----- t_user表 有" + count + "条数据");
}
Test:
5. 查询实体对象User
可以使用两种方式获取
/**
* @Description: 查询实体类
* 如果实体类属性名和表字段名一致 使用BeanPropertyRowMapper自动映射
* 不一致,使用new RowMapper 使用resultSet填充对象。转为lambda表达式如下user2
*/
@Test
public void testEntity() {
JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
User user1 = jdbcTemplate.queryForObject("select * from t_user where id=1", new BeanPropertyRowMapper<>(User.class));
System.out.println(user1);
User user2 = jdbcTemplate.queryForObject("select * from t_user where id=2",
((resultSet, i) -> {
User user = new User();
user.setId(resultSet.getInt("id"));
user.setName(resultSet.getString("name"));
user.setAge(resultSet.getInt("age"));
user.setGender(resultSet.getString("gender"));
return user;
}));
System.out.println(user2);
}
Test:
6. 向表中插入(insert)数据
/**
* @Description: 插入
*/
@Test
public void testInsert() {
JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
int insert= jdbcTemplate.update("insert into t_user(name,age,gender) values (?,?,?)", "小学徒", 20, "男");
System.out.println(insert);
}
Test:
查看数据库验证
7. 修改(update)表数据
/**
* @Description: 修改
*/
@Test
public void testUpdate() {
JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
int update = jdbcTemplate.update("update t_user set age=? where id=?", 30, 5);
System.out.println(update);
}
Test:
数据库查看验证
8. 删除(delete)表数据
/**
* @Description: 删除
*/
@Test
public void testDelete() {
JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class);
int update = jdbcTemplate.update("delete from t_user where id=?", 5);
System.out.println(update);
}
Test:
数据库查看验证
9. 使用具名函数
xml配置
<!--具名函数-->
<bean class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate" name="namedParameterJdbcTemplate">
<constructor-arg type="javax.sql.DataSource" ref="dataSource"/>
</bean>
/**
* @Description: 使用具名函数jdbcTemplate,参数用map传入
*/
@Test
public void testNamedParameterJdbcTemplate() {
NamedParameterJdbcTemplate namedParameterJdbcTemplate = context.getBean(NamedParameterJdbcTemplate.class);
Map<String, Object> map = new HashMap<>();
map.put("id", 1);
User user = namedParameterJdbcTemplate.queryForObject("select * from t_user where id=:id", map, new BeanPropertyRowMapper<>(User.class));
System.out.println(user);
}
Test: