}
多个人同时需改一条记录,最后提交的会把之前提交的数据覆盖更新。
6.1、丢失更新解决方案:
6.1.1 、悲观锁(表级锁):串行操作。
举例1:如上图修改数据,Lucy修改money数据时,别人都不能进行操作,只有lucy操作完成后,其他人才能操作。
举例2:又比如当一个人上网浏览新闻时,别人不能浏览,只有当这个人浏览完成后,别人才能浏览,如果这个人浏览一百年,其他所有人就要等一百年,这就是悲观锁。
6.1.2、 乐观锁
使用版本号进行并发的控制。比如多个人修改数据时,只有一个人才能修改成功,其他人不能同时修改。
乐观锁的实现原理:
乐观锁的具体实现:
mybatis-plus实现乐观锁官方步骤:https://mp.baomidou.com/guide/interceptor-optimistic-locker.html#optimisticlockerinnerinterceptor
- 1、表中添加字段,作为乐观锁版本号。
- 2、对应实体类添加版本号属性。
@version注解所在的包:
- 3、插件配置
spring工程:在spring.xml配置文件中
spring-boot项目:新建一个存放配置类的包,在该包下新建个配置类:编写乐观锁插件
package com.nonglin.mpdemo.config;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan(“com.nonglin.mpdemo”)
public class Mpconfig {
//乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
- 4、在测试类中测试乐观锁:
//测试乐观锁
@Test
public void testOptimisticLocker(){
User user = userMapper.selectById(1363307390618947585L);
user.setAge(1);
int row = userMapper.updateById(user);
System.out.println(“修改”+row+“条数据”);
}
7.1、根据id查询记录
//根据id查询
@Test
public void findById(){
User user = userMapper.selectById(1L);
System.out.println(user);
}
控制台输出:
DBC Connection [HikariProxyConnection@671981276 wrapping com.mysql.cj.jdbc.ConnectionImpl@28fd3dc1] will not be managed by Spring
==> Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id=?
==> Parameters: 1(Long)
<== Columns: id, name, age, email, create_time, update_time, version
<== Row: 1, Jone, 18, test1@baomidou.com, null, null, null
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35342d2f]
User(id=1, name=Jone, age=18, email=test1@baomidou.com, createTime=null, updateTime=null, version=null)
7.2、过多个id批量查询
//多个id批量查询
@Test
public void findByBatchIds(){
List users = userMapper.selectBatchIds(Arrays.asList(1L,2L,3L));
for(User user:users){
System.out.println(user);
}
}
控制台输出:
JDBC Connection [HikariProxyConnection@1171672359 wrapping com.mysql.cj.jdbc.ConnectionImpl@34fe326d] will not be managed by Spring
==> Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id IN ( ? , ? , ? )
==> Parameters: 1(Long), 2(Long), 3(Long)
<== Columns: id, name, age, email, create_time, update_time, version
<== Row: 1, Jone, 18, test1@baomidou.com, null, null, null
<== Row: 2, Jack, 120, test2@baomidou.com, null, null, null
<== Row: 3, Tom, 28, test3@baomidou.com, null, null, null
<== Total: 3
打印输出:
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@65eabaab]
User(id=1, name=Jone, age=18, email=test1@baomidou.com, createTime=null, updateTime=null, version=null)
User(id=2, name=Jack, age=120, email=test2@baomidou.com, createTime=null, updateTime=null, version=null)
User(id=3, name=Tom, age=28, email=test3@baomidou.com, createTime=null, updateTime=null, version=null)
7.3、简单的条件查询
//简单条件查询
@Test
public void estSelectByMap(){
HashMap<String,Object> map = new HashMap<>();
map.put(“name”,“Lucy”);
map.put(“age”,18);
List users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
控制台输出:
JDBC Connection [HikariProxyConnection@774095232 wrapping com.mysql.cj.jdbc.ConnectionImpl@499683c4] will not be managed by Spring
==> Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user WHERE name = ? AND age = ?
==> Parameters: Lucy(String), 18(Integer)
<== Columns: id, name, age, email, create_time, update_time, version
<== Row: 1363104207493660674, Lucy, 18, Lucy@qq.com, null, null, null
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2b917fb0]
User(id=1363104207493660674, name=Lucy, age=18, email=Lucy@qq.com, createTime=null, updateTime=null, version=null)
MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能
(1)创建配置类
在配置类中添加插件
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
(2)测试selectPage分页
测试:最终通过page对象获取相关数据
//测试分页插件
@Test
public void testPage(){
//创建page参数
//传入两个参数 当前页和每页显示的记录数
Page page = new Page<>(1,4);
//调用mybatis-plus分页查询的方法
//调用mybatis-plus分页查询过程中底层进行了封装,把分页所有数据封装到page中
userMapper.selectPage(page,null);
//通过page对象获取分页数据
System.out.println(“当前页”+page.getCurrent());//当前页
System.out.println(“每页数据list集合”+page.getRecords());//每页数据list集合
System.out.println(“每页显示记录数”+page.getSize());//每页显示记录数
System.out.println(“总记录数”+page.getTotal());//总记录数
System.out.println(“总页数”+page.getPages());//总页数
System.out.println(“是否有上一页”+page.hasPrevious());//是否有上一页
System.out.println(“是否有下一页”+page.hasNext());//是否有下一页
}
控制台输出:
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@71f96dfb] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@1545644729 wrapping com.mysql.cj.jdbc.ConnectionImpl@4b7c4456] will not be managed by Spring
JsqlParserCountOptimize sql=SELECT id,name,age,email,create_time,update_time,version FROM user
==> Preparing: SELECT COUNT(1) FROM user
==> Parameters:
<== Columns: COUNT(1)
<== Row: 11
==> Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user LIMIT 0,4
==> Parameters:
<== Columns: id, name, age, email, create_time, update_time, version
<== Row: 1, Jone, 18, test1@baomidou.com, null, null, null
<== Row: 2, Jack, 120, test2@baomidou.com, null, null, null
<== Row: 3, Tom, 28, test3@baomidou.com, null, null, null
<== Row: 4, Sandy, 21, test4@baomidou.com, null, null, null
<== Total: 4
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@71f96dfb]
当前页1
每页数据list集合[User(id=1, name=Jone, age=18, email=test1@baomidou.com, createTime=null, updateTime=null, version=null), User(id=2, name=Jack, age=120, email=test2@baomidou.com, createTime=null, updateTime=null, version=null), User(id=3, name=Tom, age=28, email=test3@baomidou.com, createTime=null, updateTime=null, version=null), User(id=4, name=Sandy, age=21, email=test4@baomidou.com, createTime=null, updateTime=null, version=null)]
每页显示记录数4
总记录数11
总页数3
是否有上一页false
是否有下一页true
9.1、物理删除
真的从数据库中将数据删除
//根据id删除
@Test
public void deleteById(){
int result = userMapper.deleteById(1363126056508198913L);
System.out.println(result);
}
//批量删除
@Test
public void testDeleteBatchIds(){
int result = userMapper.deleteBatchIds(Arrays.asList(1L,2L,3L));
System.out.println(result);
}
9.2、逻辑删除
并没有将数据从数据库中删除,数据还存在数据库中,只是查询时查不出来数据了。
第一步:表添加逻辑删除字段,对应实体类添加属性,属性添加注解。
第二步:在项目的配置类中配置逻辑删除插件
(mp3.3版本之后不需要引入该插件页可以实现功能)
//逻辑删除插件
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
第三步:application.properties 加入配置
#逻辑删除配置
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
第四步:测试逻辑删除
/**
- 测试 逻辑删除
*/
@Test
public void testLogicDelete() {
int result = userMapper.deleteById(1L);
System.out.println(result);
}
- 测试后发现,数据并没有被删除,deleted字段的值由0变成了1
- 测试后分析打印的sql语句,是一条update
总结
-
对于框架原理只能说个大概,真的深入某一部分具体的代码和实现方式就只能写出一个框架,许多细节注意不到。
-
算法方面还是很薄弱,好在面试官都很和蔼可亲,擅长发现人的美哈哈哈…(最好多刷一刷,不然影响你的工资和成功率???)
-
在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。
-
要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!
第一次跳槽十分忐忑不安,和没毕业的时候开始找工作是一样的感受,真的要相信自己,有条不紊的进行。如果有我能帮忙的地方欢迎随时找我,比如简历修改、内推、最起码,可以把烦心事说一说,人嘛都会有苦恼的~
祝大家都有美好的未来,拿下满意的 offer。