MyBatisPlus 学习笔记_MP的AR模式

img
pojo(实体类)

  • extends Model : 必须存在对应的原始mapper并继承baseMapper并且可以使用的前提下才能使用此 AR 模式 !!!

文章末尾有关于AR模式的简单介绍

@Data
@TableName("user")
public class User extends Model<User> {@TableIdprivate Long id;private String name;private Integer age;private String email;private Long managerId;private LocalDateTime createTime;
}

mapper接口(dao层):

// 在对应的Mapper上面继承基本的接口 BaseMapper
@Repository // 代表持久层
public interface UserMapper extends BaseMapper<User> {// 所有的CRUD操作都已经基本完成了// 你不需要像以前的配置一大堆文件了
}

Service层:

import com.baomidou.mybatisplus.extension.service.IService;
import com.zhixi.pojo.User;public interface UserService extends IService<User> {
}

Service层实现类:

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}

启动类:

  • 注意点:我们需要在主启动类上去扫描我们的mapper包下的所有接口

img

测试类中测试

@SpringBootTest
class MybatisPlusApplicationTests {// 继承了BaseMapper,所有的方法都来自父类// 我们也可以编写自己的扩展方法@AutowiredUserMapper userMapper;@Testvoid contextLoads() {// 参数是一个 Wrapper , 条件构造器,这里我们先不用 null// 查询全部用户List<User> users = userMapper.selectList(null);users.forEach(System.out::println);}
}

思考问题:

1、SQL是谁帮我们写的?MyBatis-Plus都写好了

2、方法哪里来的?MyBatis-Plus 都写好了

二、配置日志

我们所有的sqld现在都是不可见的,我们希望知道它是怎么执行的,所以我们必须要看日志!

# 配置日志 (系统自带的,控制台输出)
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

配置完毕日志之后,后面的学习就需要注意这个自动生成的SQL,你们就会喜欢上MyBatis-Plus !

三、CRUD

1. 插入操作

Insert 插入

@Test
public void testInsert() {User user = new User();user.setName("Dainel");user.setAge(3);user.setEmail("daniel@alibaba.com");int result = userMapper.insert(user);// 帮我们自动生成idSystem.out.println(result);// 受影响的行数System.out.println(user);// 发现: id自动回填
}

数据库插入的id默认值为:全局的唯一id

2. 主键生成策略

默认 ID_WORKER 全局唯一id

分布式系统唯一id生成:https://www.cnblogs.com/haoxinyue/p/5208136.html

雪花算法:

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯一!

主键自增

我们需要配置主键自增:

  1. 实体类字段上 @TableId(type = IdType.AUTO)

  2. 数据库字段上一定是自增的

    img

  3. 再次测试即可

其余的源码解释

public enum IdType {AUTO(0), // 数据库id自增NONE(1), // 未设置主键INPUT(2), // 手动输入,自己写idID_WORKER(3), // 默认的全局唯一idUUID(4), // 全局唯一id uuidID_WORKER_STR(5); // ID_WORKER 字符串表示法
}

3、更新操作

@Test/*更新操作*/
void updateUser() {// 查询到要更新的用户User user = userMapper.selectById(7);// 要更新的值user.setName("demo");user.setAge(21);// 执行更新userMapper.updateById(user);
}

4. 自动填充

创建时间、修改时间!这些个操作一般都是自动化完成的,我们不希望手动更新!

阿里巴巴开发手册:所有的数据库表:gmt_create、gmt_modified几乎所有的表都要配置上!而且需要自动化!

方式一:数据库级别(工作中不允许修改数据库)

  1. 在表中新增字段 create_time,update_time;注意将更新的时间戳勾选

    img

  2. 再次测试插入方法,我们需要先把实体类同步

    private Date createTime;
    private Date updateTime;
    
  3. 再次查看更新结果即可

img

方式二:代码级别

  1. 删除数据库中的默认值、更新操作

  2. 实体类的字段属性上需要增加注解

    //字段添加填充内容
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;@TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    
  3. 编写处理器来处理这个注解即可:handler/MyMetaObjectHandler

    package com.kuang.handler;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.ibatis.reflection.MetaObject;
    import org.springframework.stereotype.Component;import java.util.Date;@Slf4j
    @Component // 一定不要忘记把处理器加到IOC容器中
    public class MyMetaObjectHandler implements MetaObjectHandler {// 插入时候的填充策略@Overridepublic void insertFill(MetaObject metaObject) {log.info("start insert fill ...");// setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)this.setFieldValByName("createTime", new Date(), metaObject);this.setFieldValByName("updateTime", new Date(), metaObject);}// 更新时的填充策略@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill ...");this.setFieldValByName("updateTime", new Date(), metaObject);}}
    
  4. 测试插入

  5. 测试更新,观察时间已经更新

img

5. 乐观锁

在面试过程中,我们经常会被问到乐观锁,悲观锁。

乐观锁:顾名思义,它总是认为不会出现问题,无论干什么都不去上锁!如果出现了问题,再次更新值测试!

悲观锁:顾名思义,它总是认为总是出现问题,无论干什么都上锁!再去操作!

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

测试一下MyBatisPlus的插件:

1、数据库中增加一个version字段,并设置默认值为1

2、实体类添加注解

@Version // 乐观锁的version注解
private Integer version;

3、编写配置

config/MybatisPlusConfig

// 配置,会被spring扫描到
@Configuration
public class MybatisPlusConfig {// 注册乐观锁@Beanpublic OptimisticLockerInterceptor optimisticLockerInnerInterceptor(){return new OptimisticLockerInterceptor();}
}

4、测试方法

测试乐观锁成功:

将2号的姓名改为lipu。看他的version会怎么变化

@Test
void OptimisticLock() {// 查询到要进行更新的用户User user = userMapper.selectById(2);// 修改用户的属性user.setName("lipu");user.setAge(28);// 提交更新userMapper.updateById(user);
}

img

测试乐观锁失败(多线程下)

// 测试乐观锁失败!多线程下
@Test
public void testVersionFall() {// 线程1User user1 = userMapper.selectById(9);user1.setName("fan111");user1.setAge(14);// 线程2User user2 = userMapper.selectById(9);user2.setName("fan222");user2.setAge(24);userMapper.updateById(user2);//自旋锁来多次尝试提交!userMapper.updateById(user1); //如果没有乐观锁就会覆盖插队线程的值
}

img

6. 查询操作

// 测试查询
@Test
public void testSelectById(){User user = userMapper.selectById(1);System.out.println(user);
}// 批量查询
@Test
public void testSelectByBatchIds(){List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));users.forEach(System.out::println);
}// 按照条件查询之一使用 map
@Test
public void testSelectByMap(){HashMap<String, Object> map = new HashMap<>();// 自定义要查询map.put("name","Dainel");map.put("age","6");List<User> users = userMapper.selectByMap(map);users.forEach(System.out::println);
}

7、分页查询

分页网站频繁使用

  1. 原始使用limit进行分页
  2. pageHelper第三方插件
  3. MybatisPlus内置了分页插件

如何使用:

1、配置分页拦截器:config/MybatisPlusConfig

  // 分页插件@Beanpublic PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();}

2、编写查询

 // 分页查询@Testvoid selectLimit() {Page<User> page = new Page<User>(2, 5);// 获取通过分页查询到的记录条数page.getRecords().forEach(System.out::println);// 查询userMapper.selectPage(page, null);// 查询总记录条数System.out.println("总计数条数:" + page.getTotal());}

img

8. 删除操作

// 测试删除
@Test
public void testdelete(){userMapper.deleteById(6L);
}// 测试批量删除
@Test
public void testdeleteBatchId(){userMapper.deleteBatchIds(Arrays.asList(1,14));
}//通过map删除
@Test
public void testDeleteByMap(){HashMap<String, Object> map = new HashMap<>();map.put("name","KUANG");userMapper.deleteByMap(map);
}

我们在工作中会遇到一些问题:逻辑删除!

9. 逻辑删除

物理删除:从数据库中直接移除

逻辑删除:在数据库中没有被移除,而是通过一个变量让他生效!deleted=0 --> deleted=1

管理员可以查看被删除的记录!防止数据的丢失!类似于回收站!

步骤:

1、在数据库表中增加一个deleted字段

img

2、修改实体类

// 表逻辑删除
@TableLogic
private int deleted;

3、配置:config/MybatisPlusConfig

注意:在新版本的MP中,不需要再写逻辑删除配置了,知道就行,只需要在实体类逻辑删除字段上加上注解即可!

// 逻辑删除组件
public ISqlInjector sqlInjector(){return new LogicSqlInjector();
}

4、properties配置(默认,可以不配置)

# 配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

测试逻辑删除:

 // 逻辑删除@Testvoid deleteLogic() {userMapper.deleteById(1);}

img

逻辑删除成功、

img

我们通过查询1号用户,验证下看是否能够查询的到:

img

四、性能分析插件

PerformanceInterceptor在3.2.0被移除了,如果想进行性能分析,用第三方的,官方这样写的“该插件 3.2.0 以上版本移除推荐使用第三方扩展 执行 SQL 分析打印 功能

https://baomidou.com/guide/p6spy.html

我们在平时的开发中,会遇到一些慢sql。解决方案:测试,druid监控…

作用:性能分析拦截器,用于输出每条SQL语句及其执行时间

MyBatisPlus也提供性能分析插件,如果超过这个时间就停止运行!

1、导入插件

// SQL执行效率插件
@Bean
@Profile({"dev","test"})
public PerformanceInterceptor performanceInterceptor(){PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();performanceInterceptor.setMaxTime(100); //ms 设置sql执行的最大时间,如果超过了则不执行performanceInterceptor.setFormat(true); // 是否格式化return performanceInterceptor;
}

记住,要在SpringBoot中配置环境为dev或者test环境!

# 开发环境
spring.profiles.active=dev

2、测试使用

 // 分页查询@Testvoid selectLimit() {Page<User> page = new Page<User>(1, 5);// 获取通过分页查询到的记录条数page.getRecords().forEach(System.out::println);// 查询userMapper.selectPage(page, null);// 查询总记录条数System.out.println("总计数条数:" + page.getTotal());}

img

只要超出时间就会抛出异常

使用性能分析插件可以提高效率,新版本MP已经移除该拆件了,可以使用druid

五、代码自动生成**非常NB

dao、pojo、service、controller都给我自己去编写完成!

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、

Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

只需要改实体类名字 和包名 还有 数据库配置即可

需要使用到的pom依赖:

 <dependencies><!--swagger依赖--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.7.0</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.7.0</version></dependency><!-- 模板引擎 --><dependency><groupId>org.apache.velocity</groupId><artifactId>velocity-engine-core</artifactId><version>2.0</version></dependency><!--导入mysql驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies>

测试代码:/test/…

package com.zhixi;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;import java.util.ArrayList;// 代码自动生成器
public class zhixiCode {public static void main(String[] args) {// 需要构建一个 代码自动生成器 对象AutoGenerator mpg = new AutoGenerator();// 配置策略// 1、全局配置GlobalConfig gc = new GlobalConfig();// 代码输出到哪个目录(获取到项目目录)String projectPath = System.getProperty("user.dir");gc.setOutputDir(projectPath + "/src/main/java");// 设置作者gc.setAuthor("张志喜");// 是否打开资源管理器(生成完代码打开目录)gc.setOpen(false);// 是否覆盖原来的文件gc.setFileOverride(false);// 去掉IService的I前缀(正则)gc.setServiceName("%sService");// 设置字段gc.setIdType(IdType.ID_WORKER);gc.setDateType(DateType.ONLY_DATE);// 配置swaggergc.setSwagger2(true);mpg.setGlobalConfig(gc);//2、设置数据源DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://182.92.209.212:3306/mybatis_plus?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai");dsc.setDriverName("com.mysql.cj.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("密码");// 数据库类型dsc.setDbType(DbType.MYSQL);mpg.setDataSource(dsc);//3、包的配置(只需要改实体类名字 和包名 还有 数据库配置即可)PackageConfig pc = new PackageConfig();// 模块名pc.setModuleName("blog");// 设置类放在哪个包下pc.setParent("com.kuang");// 设置实体类pc.setEntity("entity");// 设置mapperpc.setMapper("mapper");// 设置services层pc.setService("service");// 设置controller层pc.setController("controller");mpg.setPackageInfo(pc);//4、策略配置StrategyConfig strategy = new StrategyConfig();// 设置要映射的表名strategy.setInclude("blog_tags", "course", "links", "sys_settings", "user_record", " user_say");// 设置下划线转驼峰命名strategy.setNaming(NamingStrategy.underline_to_camel);strategy.setColumnNaming(NamingStrategy.underline_to_camel);// 自动lombok;strategy.setEntityLombokModel(true);// 设置逻辑删除列名strategy.setLogicDeleteFieldName("deleted");// 自动填充配置TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);/*创建时间*/TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);/*修改时间*/ArrayList<TableFill> tableFills = new ArrayList<>();tableFills.add(gmtCreate);tableFills.add(gmtModified);// 添加自动填充strategy.setTableFillList(tableFills);// 乐观锁strategy.setVersionFieldName("version");/*设置版本字段名称*/strategy.setRestControllerStyle(true);strategy.setControllerMappingHyphenStyle(true);// localhost:8080/hello_id_2mpg.setStrategy(strategy);mpg.execute(); //执行}
}

img

六、SQL注入器:实现自定义通用方法

MP在一开始就给大家提供了很多通用的方法,在DefaultSqlInjector这个类中,在MethodList这个集合当中包含的都是通用方法类,如果想要使用自定义通用方法,也需要添加到这个集合当中。

/*** SQL 默认注入器*/
public class DefaultSqlInjector extends AbstractSqlInjector {@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass) {return Stream.of(new Insert(),new Delete(),new DeleteByMap(),new DeleteById(),new DeleteBatchByIds(),new Update(),new UpdateById(),new SelectById(),new SelectBatchByIds(),new SelectByMap(),new SelectOne(),new SelectCount(),new SelectMaps(),new SelectMapsPage(),new SelectObjs(),new SelectList(),new SelectPage()).collect(toList());}
}

第一步:创建自定义方法的类(以创建删除所有记录的方法为例)

类名是DelFillUserMethod,这个是自定义的,但是最好是见名知意的类名。
继承AbstractMethod抽象类,AbstractMethod是抽象的注入方法类,每个通用方法也都继承了这个类,也是为了方便调用里面的方法
重写injectMappedStatement方法,injectMappedStatement内是我们完成我们这个方法具体的逻辑。

package com.zhixi.method;import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;/**
* @author zhangzhixi
* @date 2021-6-13 20:56
*/
public class DelAllMethod extends AbstractMethod {@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {// 1、自定义执行的sql语句String sql = "delete from " + tableInfo.getTableName();// 2、mapper接口方法名String method = "deleteUserAll";/*** 3、添加动态SQL标签处理器* 注意只需要传入sql即可*/SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);// 4、返回statement对象return addDeleteMappedStatement(mapperClass, method, sqlSource);}
}

第二步:创建注入器,并把自定义的方法添加到集合当中

  • 类名是CustomSqlInjector,自定义的
  • 继承DefaultSqlInjector并重写getMethodList,SQL 默认注入器上面也有提到过,我们得把我们自定义的方法加入到通用方法的集合methodList当中
 package com.zhixi.injector;import com.baomidou.mybatisplus.core.injector.AbstractMethod;import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;import com.zhixi.method.DelAllMethod;import org.springframework.stereotype.Component;import java.util.List;@Componentpublic class MyInjector extends DefaultSqlInjector {@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass) {// 1、先要通过父类方法,获取到原有的集合,不然会自带的通用方法会失效的List<AbstractMethod> methodList = super.getMethodList(mapperClass);// 2、添加自定义mapper类methodList.add(new DelAllMethod());return methodList;}}

第三步:在Mapper中添加自定义的方法

package com.zhixi.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zhixi.pojo.User;
import org.springframework.stereotype.Repository;@Repository
public interface UserMapper extends BaseMapper<User> {/*** 删除所有记录** @return 影响行数*/int deleteUserAll();
}

什么是AR模式:简单来说就是通过实体类对象,直接进行表的增删改查操作。

实现AR模式在MP中有两个基本要求:

  1. 实体类继承Model类
//如果不加下面第二个注解,会报一个警告(自动调用equals和hashcode方法,没有调用父类的)
@Data
@EqualsAndHashCode(callSuper = false)
public class User extends Model<User> {...
}
  1. 必须存在原始的Mapper接口并继承BaseMapper
public interface UserMapper extends BaseMapper<User> {...
}

实战演练:

package com.mp.first;import com.mp.first.entity.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)
@SpringBootTest
public class ARTest {/*** 这里就不用再注入userMapper了,直接操作实体类就好*/@Testpublic void insert(){User user = new User();user.setName("老刘");user.setAge(18);user.setEmail("liu@qq.com");boolean insert = user.insert();System.out.println("插入是否成功:"+insert);}@Testpublic void selectById(){User user = new User();User userSelect = user.selectById(1321469479649107970L);System.out.println("查到了:"+userSelect);}@Testpublic void selectById2(){User user = new User();user.setId(1321469479649107970L);User userSelect = user.selectById();System.out.println("查到了:"+userSelect);}@Testpublic void updateById(){User user = new User();user.setId(1321469479649107970L);user.setName("老王");boolean userSelect = user.updateById();System.out.println(userSelect);}@Testpublic void deleteById(){User user = new User();user.setId(1321469479649107970L);boolean userSelect = user.deleteById();System.out.println(userSelect);}//    SELECT id,name,age,email FROM user WHERE id=?
//    UPDATE user SET name=?, age=?, email=? WHERE id=?@Testpublic void insertOrUpdate(){User user = new User();//不传入id时,是做新增操作user.setName("老牛");user.setAge(58);user.setEmail("laoniu@qq.com");//传入id时,会先在数据库中找;如果没有此id,怎做新增操作,如果有此id则做修改操作user.setId(1321473206095212546L);boolean insert = user.insertOrUpdate();System.out.println(insert);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555074.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ajax调用java程序,从微信小程序到鸿蒙JS开发-JS调用Java

除轻量级智能穿戴设备&#xff0c;现鸿蒙支持的手机、汽车、TV、手表、平板等属于富鸿蒙&#xff0c;在JS语言的项目中也有Java模块&#xff0c;并提供了JS跨语言调用Java方法的技术。现需要实现查看商品评论时&#xff0c;统计出长评、中评和短评的比例&#xff0c;这里将评论…

文本删除空行_010 Editor for mac(文本和十六进制编辑器)

为大家带来最新版本的010 Editor for mac&#xff0c;这是一款专业的文本和十六进制编辑器&#xff0c;新版本的010 editor mac版包含了语法突出显示、更多字符集支持、添加了删除行和删除空行命令等新功能&#xff0c;另外修复了各种错误&#xff0c;功能更加全面。010editor …

Mybatis-Plus之四种lambda方式LambdaQueryWrapper,QueryWrapper<实体>().lambda(),LambdaQueryChainWrapper<实体>

Mybatis-Plus之四种lambda方式 lambda四种表达形式 前言 使用了lambda表达式 可以通过方法引用的方式来使用实体字段名的操作&#xff0c;避免直接写数据库表字段名时的错写名字&#xff1b; 一、LambdaQueryWrapper<> /*** lambda 条件构造器* 生成的sql语句 SELECT…

sql怎么修改服务器角色,sql角色服务器的设置

sql角色服务器的设置 内容精选换一换如果您需要对华为云上购买的DDM资源&#xff0c;为企业中的员工设置不同的访问权限&#xff0c;为达到不同员工之间的权限隔离&#xff0c;您可以使用统一身份认证服务(Identity and Access Management&#xff0c;简称IAM)进行精细的权限管…

MyBatis-Plus——字段类型处理器TypeHandler

字段类型处理器&#xff08;TypeHandler&#xff09; 1&#xff0c;准备工作 &#xff08;1&#xff09;MyBatis 中的 TypeHandler 类型处理器用于 JavaType 与 JdbcType 之间的转换&#xff0c;假设我们用户表中有一个联系方式字段&#xff0c;类型为字符串&#xff1a; &am…

额外参数_Pytorch获取模型参数情况的方法

分享人工智能技术干货&#xff0c;专注深度学习与计算机视觉领域&#xff01;相较于Tensorflow&#xff0c;Pytorch一开始就是以动态图构建神经网络图的&#xff0c;其获取模型参数的方法也比较容易&#xff0c;既可以根据其内建接口自己写代码获取模型参数情况&#xff0c;也可…

Mybatis-Plus之逻辑删除

概念 什么是逻辑删除 逻辑删除:假删除。将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录。 数据库实现思路:插入数据时,标记为未删除状态;查询、修改时,只获取未删除状态的数据进行操作;删除时则更新删除状态为已删除…

查看分支编码_MySQL分支数据库MariaDB之CentOS安装教程

MariaDB数据库管理系统是MySQL的一个分支&#xff0c;由MySQL的创始人Michael Widenius主持开发。采用GPL授权许可 MariaDB的目的是完全兼容MySQL&#xff0c;包括API和命令行&#xff0c;在存储引擎方面&#xff0c;使用XtraDB(英语&#xff1a;XtraDB)来代替MySQL的InnoDB。1…

关联规则算法c语言样例及分析_推荐系统总结系列-关联规则算法(四)

基于关联规则的推荐有三种方法&#xff1a;Apriori关联规则算法FP Tree关联规则算法&#xff1b;PrefixSpan关联规则算法&#xff1b;关联规则挖掘推荐算法&#xff1a;关联规则挖掘是一种在大规模交易中识别类似规则关系模式的通用技术&#xff0c;可以应用到推荐系统中。交易…

Mysql - Innodb锁、事务与隔离级别

我们的数据库一般都会并发执行多个事务&#xff0c;多个事务可能会并发的对相同的一批数据进行增删改查操作&#xff0c;可能就会导致脏写、脏读、不可重复读、幻读这些问题。 这些问题的本质都是数据库的多事务并发问题&#xff0c;为了解决多事务并发问题&#xff0c;数据库…

语言非递归求解树的高度_算法素颜(11):无死角“盘”它!二分查找树

引言《菜鸟也能“种”好二叉树&#xff01;》一文中提到了&#xff1a;为了方便查找&#xff0c;需要进行分层分类整理。而满足这种目标的数据结构之一就是树。树的叶子节点可以看作是最终要搜寻的目标物&#xff1b;叶子节点以上的每一层&#xff0c;都可以看作是一个大类别、…

Mysql InnoDB存储引擎的锁相关

Mysql InnoDB存储引擎的锁相关 InnoDB下&#xff0c;mysql四个级别隔离下加锁操作 四个级别隔离的写操作都加X锁串行化下读加S锁select … for update, select … lock in share mode 分别加x锁&#xff0c;s锁在需要加锁的场景下&#xff0c;会根据情况使用三种加锁策略&…

显示器尺寸对照表_电脑显示器尺寸对照表一览,教你怎么选择最适合自己的显示器尺寸...

显示小课堂&#xff1a;显示器买大买小谁说了算&#xff1f; [本文来自&#xff1a;www.ii77.com]今天&#xff0c;笔者想和大家讨论一下关于显示器尺寸选择方面的问题。通过这两年显示器行业的发展我们不难看出&#xff0c;现在显示器的尺寸越来越大&#xff0c;三十几吋、四十…

MySQL事务隔离级别理解_解读MYSQL的可重复读、幻读及实现原理

前言 提到事务&#xff0c;你肯定不会陌生&#xff0c;最经典的例子就是转账&#xff0c;甲转账给乙100块&#xff0c;当乙的账户中到账100块的时候&#xff0c;甲的账户就应该减去100块&#xff0c;事务可以有效的做到这一点。 在MySQL中&#xff0c;事务支持实在引擎层实现的…

MySQL 是如何实现四大隔离级别的?

MySQL 是如何实现四大隔离级别的&#xff1f; 在mvcc下&#xff0c;mysql中用到的锁还是共享锁和排他锁么&#xff1f;如果是的话&#xff0c;那么是怎样结合锁和mvcc来实现rc和rr隔离级别的呢&#xff1f;还有mysql中在ru隔离级别下&#xff0c;两个事务同时读取数据对象A&am…

Linux命令 移动/复制文件/目录到指定目录下

1、同一个服务器下复制文件或文件夹 1.1 复制文件 复制文件&#xff1a;把1.txt 复制到根目录下的sbin目录 cp 文件名&#xff08;可带路径&#xff09;目标路径&#xff08;带路径&#xff09;如&#xff1a;cp 1.txt ~/sbin/1,2 复制目录 复制目录&#xff1a;把relea…

c mysql web开发实例教程_Web开发(六)MySql

数据库简介数据库(DB)数据库(database&#xff0c;DB)是指长期存储在计算机内的&#xff0c;有组织&#xff0c;可共享的数据的集合。数据库中的数据按一定的数学模型组织、描述和存储&#xff0c;具有较小的冗余&#xff0c;较高的数据独立性和易扩展性&#xff0c;并可为各种…

Git——工作中使用命令详解

1、Linux常用命令 cd&#xff1a;改变目录cd…&#xff1a;返回上级目录pwd&#xff1a;显示当前目录clear&#xff1a;清屏ls&#xff1a;显示当前目录所有文件touch&#xff1a;添加文件rm&#xff1a;删除文件mkdir&#xff1a;新建文件夹rm -r&#xff1a;删除文件夹mv&am…

Java中常见null简析

对于每一个Java程序员来说,null肯定是一个让人头痛的东西,今天就来总结一下Java中关于null的知识。 1.null不属于任何类型,可以被转换成任何类型,但是用instanceof永远返回false. 2.null永远不能和八大基本数据类型进行赋值运算等,否则不是编译出错,就是运行出错. 3.null可以…

Chrome浏览器F5和ctrl+F5的区别

一、正常重新加载&#xff08;F5&#xff0c;Ctrl R&#xff0c;在地址栏回车&#xff0c;点击链接&#xff09; 本节中的操作&#xff1a;根据缓存的缓存策略&#xff0c;进行处理。如果缓存没过期&#xff0c;就不向浏览器发请求&#xff0c;而是直接使用缓存。 F5或Contr…