springboot权限管理系统 学习(四)

Durid 连接池

连接池技术预先建立多个数据库连接对象,然后将连接对象保存到连接池中,当客户请求到来时,从池中取出一个连接对象为客户服务,当请求完成后,客户程序调用close0方法,将连接对象放回池中。

优势比较:Durid功能比较全;HikariCP速度比较快

添加Durid依赖

我之前试的是1.1.10,发现导包导不进去,于是用了1.1.9,就可以导入进去了

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.9</version>
        </dependency>

导入能够运行成功,但是配置的时候出现了initial-size不一致的情况,然后新建一个config文件,配置config
在这里插入图片描述
出现这个情况的话,我们新建一个config文件,下面再设置一个DuridConfig文件,文件内容如下所示

@Configuration
public class DruidConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource getDataSource(){
        return new DruidDataSource();
    }
}

最后写完debug一下,正好都是自己设置的属性
在这里插入图片描述

使用注解方式完成数据表CRD的操作

Mapper 注解

1、为了把mapper这个DAO交给Spring容器 IOC管理
2、为了不再写mapper映射文件(一个是注解,一个以.xml的形式)
3、添加@Mapper注解的接口生成一个实现类

在这里插入图片描述

@Select注解

一般数据表里面写的是这样:例如username或者user_name
1、采用mapUnderscoreToCamelCase:true 驼峰命名的方式来解决
在这里插入图片描述
2、@Results / @ResultMap注解的方式
3、数据库字段别名方式

通常采用第一种方式:直接放在yml文件里面配置

动态SQL:#{} 和${}

select * from user where name = ${name};
select * from user where name = #{name};

解析的结果都是相同的;name=hws;
预编译中处理的不一样;占位符和字符串拼接;
#的是是属于占位符的
$的是拼接的,会有漏洞

通常情况下面采用的是#形式

@Insert

不需要返回主键
在这里插入图片描述
返回自增主键:@Option
在这里插入图片描述
返回非自增主键
在这里插入图片描述

@Delete注解

在这里插入图片描述

总结流程

1、先写好annotation注解,@Mapper (注意是一个接口 interface)
2、针对不同的操作写不同的方法

使用配置的方式完成update的方式

步骤如下:
1、编写抽象方法 update

int updateUser(SysUser user);

2、配置xml扫描路径 路径下面加的xml才能找到
由于之前在yml里面已经加上了路径
在这里插入图片描述
3、编写mapper.xml

Junit单元测试

单元测试用例
1、已知输入和预期的输出,在测试执行前就已知道
2、至少有两个单元测试用例:一个正检验(成功的),一个负检验(有异常之类的)

测试时候出现的问题

Duplicate entry 'hws' for key 'username'

这个问题查了一下,发现是数据库里面已经有这个username 是hws ,于是的话,就换了一个username set进去,然后就ok了

public class DemoApplicationTests {

    @Autowired
    DataSource dataSource;

    @Resource
    UserDao userDao;

    @Test
    public void testInsertUser() {
        SysUser sysUser = new SysUser();
        sysUser.setUsername("hongweisong");
        sysUser.setPassword("123456");
        sysUser.setStatus(1);
        sysUser.setCreateTime(new Date());
        sysUser.setUpdateTime(new Date());

        userDao.save(sysUser);
    }
}

然后继续完成cURD的编码 创建(Create)、更新(Update)、读取(Retrieve)和删除(Delete)
delete:

public class DemoApplicationTests {

    @Autowired
    DataSource dataSource;

    @Resource
    UserDao userDao;

    @Test
    public void testDeleteUser() {

        userDao.deleteUser(46);
    }
}

MybatisCodeHelperPro使用:
1、下载破解的ZIP的压缩包
2、直接导入ZIP压缩包
3、onlineActivation里面随便输入
4、验证成功
在这里插入图片描述

Spring事务约定

在这里插入图片描述
1、声明式事务:@Transactional(推荐)
2、编程式事务

传播行为是方法之间调用事务采取的策略问题
在这里插入图片描述
在这里插入图片描述
propagation_required是默认的
当有两个方法时,事务A和事务B不知道先调用哪一个,所有有一个传播行为,要知道这个事务是跟着谁在走
在这里插入图片描述

事务的特性(ACID)

1、原子性:事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么全部不起作用
2、一致性:执行事务前后,数据保持一致
3、隔离性:并发访问数据库的时候,一个用户的事务不被其它事务所干扰,各个并发事务之间的数据库是独立的
4、持久性:一个事务被提交之后,它对数据库中的数据改变是永久的

事务的隔离

在这里插入图片描述
会产生 第二类丢失更新的问题

隔离级别

1、未提交读
允许一个事务读取另外一个事务没有提交的数据
并发性能比较好,对数据的一致性没有过高的要求

会产生 脏读
例如A事务还没有提交,B事务就已经读到了A数据的结果(破坏了隔离性)
在这里插入图片描述
2、读写提交
一个事务只能读取另外一个数据已经提交的数据,不能读取未提交的数据(可以克服脏读,产生不可重复读场景)
不可重复读
A事务在本次事务中,对自己未操作过的数据,进行了多次的读取,结果出现了不一致或者记录不存在的情况。(破坏了一致性,update和delete)
在这里插入图片描述
在这里插入图片描述
3、可重复读
幻读:
A事务在本次事务中,对自己未操作过的数据,进行了多次读取,第一次读取时,记录不存在;第二次读取时,记录出现了。(破坏了一致性,insert)
在这里插入图片描述

4、串行化
按照一个个的顺序来
性能最差

实际项目中,以第二个 读写提交 为主

**========================================================**
分割一下,事务总的来写一下

1 事务
事务只是一个改变,是一些的操作集合;用专业的术语去解释,就是一个程序的执行单元;事务本身并不包含这四个特性,我们需要通过某些手段,尽可能让这个执行单元满足这四个特性,那么,我们就可以称它是一个事务,或者说是一个正确的,完美的事务。

2 四特性

原子性:满足原子操作单元,对数据的操作,要么全部执行,要么全部不执行。
一致性:事务开始和完成时,数据都必须保持一致。
隔离性:事务之间相互独立,中间状态对外部不可见。
持久性:数据的修改是永久性的,即使系统出现任何故障都能够保持。

3 隔离级别

3.1 并发情况下事务引发的问题

一般情况下,多个单元操作(事务,这里的事务,并不是完美的事务)并发执行,会出现这么几个问题:
脏读:A事务还未提交,B事务就读到了A操作的结果。(破坏了隔离性)
不可重复读:A事务在本次事务中,对自己未操作过数据,进行多次读取,结果出现不一致或记录不存在的情况。(破坏了一致性,重点是update和delete)
幻读:A事务在本次事务中,先读取了一遍数据,发现数据不存在,过了一会,又读取了一遍,发现又有数据了。(破坏了一致性,重点是insert)

3.2 解决(制定标准

为了权衡『隔离』和『并发』的矛盾,ISO定义了4个事务隔离级别,每个级别隔离程度不同,允许出现的副作用也不同。

未提交读(read-uncommitted):最低级别,基本只保证持久性;会出现脏读,不可重复读,幻读的问题。
已提交读(read-committed):语句级别;会出现不可重复读,幻读的问题。
可重复读(repeatable-read):事务级别;只会出现幻读问题。
串行化(serializable):最高级别,也就是事务与事务完全串行化执行,无并发可言,性能低;但不会出现任何问题。
在这里插入图片描述

3.2 实现(InnoDB)

锁机制:阻止其他事务对数据进行操作, 各个隔离级别主要体现在读取数据时加的锁的释放时机。

RU:事务读取时不加锁

RC:事务读取时加行级共享锁(读到才加锁),一旦读完,立刻释放(并不是事务结束)。

RR:事务读取时加行级共享锁,直到事务结束时,才会释放。

SE:事务读取时加表级共享锁,直到事务结束时,才会释放。

其他还有一些细节不同,主要就是这些
MVCC机制:生成一个数据快照,并用这个快照来提供一定级别的一致性读取,也称为多版本数据控制。

实际就是『版本控制』加『读写分离』思想,主要用作于RC和RR级别。

Spring事务实践

在业务层(service)里面放相对应的隔离机制

@Transactional可以作用于类方法上面
1、当作用于上面时,该类的所有public方法都将具有该类型的事务属性
2、类内部方法调用本类内部的其它方法并不会引起事务行为
3、@Transactional注解应该只被应用到public方法上(由AOP本质决定的)

代码中:
1、在com.hws.demo下面新建一个service目录,里面先写一个interface的接口,名字叫做IUserService ,然后在这个service目录下面建立一个impl文件,文件下面放置UserServiceImpl的class
2、然后的话,在UserServiceImpl里面先写@Service进行SpringIOC的注入,在@Service下面写上@Trans
actional 注解,对应事务,
3、写完@Service和@Transactional这两个注解后,再在UserServiceImpl里面写实现implements,实现IUserService,
4、在IUserService里面写出业务逻辑,比如 int save(SysUser sysuser);
5、在UserServiceImpl里面写上@Override等方法,并且进行注入@Autowired,下面写上 dao的引入 UserDao userDao;
6、在返回return的时候写上userDao下面对应的save方法

SpringMVC结构

在这里插入图片描述

发布了12 篇原创文章 · 获赞 2 · 访问量 1547

猜你喜欢

转载自blog.csdn.net/hongweisong666/article/details/104085512
今日推荐