MybatisPlus

MybatisPlus

  • 一、MyBatisPlus基础
    • 1.1 MyBatisPlus介绍
    • 1.2 MyBatisPlus入门
    • 2. 继承BaseMapper<对应的想要返回类的类名>
    • 1.3 常用注解
      • 1.3.1 @TableName
      • 1.3.2 @Tableid
      • 1.3.3 @TableField
    • 1.4 常用配置
  • 二、条件构造器
    • 2.2 自定义SQL
    • 2.3 Service接口
    • 2.4 基于Restful风格实现下列小练习
    • 2.5 IService的Lambda查询
    • 2.6 批量删除
  • 三、拓展业务
    • 3.1 静态工具
    • 3.2 逻辑删除
    • 3.3、枚举处理器
    • 3.4 JSON处理器
    • 3.5 分页插件功能
    • 3.6 通用分页实体

一、MyBatisPlus基础

1.1 MyBatisPlus介绍

MyBatisPlus:就是相当于开发mybatis的应用小能手,能够简化我们的开发

1.2 MyBatisPlus入门

  1. 导入对应的start包,可以在这里找到对应想要的坐标信息
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatisplus-spring-boot-starter -->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatisplus-spring-boot-starter</artifactId><version>1.0.5</version>
</dependency> 

2. 继承BaseMapper<对应的想要返回类的类名>

@Mapper
public interface BookDao extends BaseMapper<Book> { 
} 

测试:

@SpringBootTest
class MyBatisPlusQuickstartApplicationTests {@Autowiredprivate BookDao bookDao;@Testvoid contextLoads() {System.out.println(bookDao.selectById(14));List<Book> books = bookDao.selectList(null);System.out.println(books);} 
}

1.3 常用注解

MvBatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息

当符合以下规定就不用进行配置,MybaitisPlus会自动识别:

  1. 类名驼峰转下划线作为表名
  2. 名为id的字段作为主键
  3. 变量名驼峰转下划线作为表的字段名

在这里插入图片描述

  • MybatisPlus中比较常用的几个注解如下
    • @TableName:用来指定表名
    • @Tableid:用来指定表中的主键字段信息
    • @TableField:用来指定表中的普通字段信息

1.3.1 @TableName

当表名和类的名字不相符合,那么就要添加这个注解来进行消除错误

在这里插入图片描述

1.3.2 @Tableid

如果主键不存在或者主键的名字不为id那么就要加上这个注解

  • ldType枚举:
    • AUTO : 数据库自增长
    • INPUT : 通过set方法自行输入
    • ASSIGN ID : 分配 ID,接口ldentifierGenerator的方法nextld来生成id默认实现类为DefaultldentifierGenerator雪花算法

1.3.3 @TableField

  • 常用的场景:
    • 成员变量名与数据库字段名不一致
    • 成员变量名以is开头,且是布尔值
    • 成员变量名与数据库关键字冲突
    • 成员变量不是数据库字段
@TableName("tbl_book")
public class Book {@TableId(type = IdType.AUTO)private Integer id;@TableField("`type`")//进行转意private String type;@TableField(exist = false) //将其表面部位数据库当中的字段private String description;private String name; public Book() {}

在这里插入图片描述

1.4 常用配置

mybatis-plus:type-aliases-package: com.itheima.mp.domain.po # 别名扫描包mapper-locations: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,默认值configuration:map-underscore-to-camel-case: true # 是否开启下划线和驼峰的映射cache-enabled: false # 是否开启二级缓存global-config:db-config:id-type: assign_id # id为雪花算法生成update-strategy: not_null # 更新笑略:只更新非空字段table-prefix: tbl_ #表面所有表面前面都加一个tbl_

这些配置不需要记下来,只需要我们需要配置的时候在官网上面进行查询

二、条件构造器

MyBatisPlus支持各种复杂的where条件,可以满足日常开发的所有需求

在这里插入图片描述

@Testvoid testQueryWrapper(){//首先编写了查询的条件QueryWrapper<Book> wrapper = new QueryWrapper<Book>().select("id","username","info","balance").like("username","o").ge("balance","1000");//进行查询操作List<Book> books = bookDao.selectList(wrapper);books.forEach(System.out::println);}

利用LambdaQueryWrapper书写:

@Testvoid testQueryWrapper(){LambdaQueryWrapper<Book> wrapper = new LambdaQueryWrapper<Book>().select(User::getId, User::getUsername, User::getInfo, User::getBalance).like(User::getUsername, "o").ge(User::getBalance, "1000");//进行查询操作List<Book> books = bookDao.selectList(wrapper);books.forEach(System.out::println);}

在这里插入图片描述

@Testvoid testQueryWrapper2(){//首先编写条件QueryWrapper<Book> wrapper = new QueryWrapper<Book>().eq("name", "jack");//然后创建需要修改的对象属性User user = new User;user.setBalance(2000);bookDao.update(user,wrapper);}

在这里插入图片描述

  @Testvoid testUpdateWrapper(){//首先编写条件List<Long> ids=List.of(1L,4L,2L);UpdateWrapper<Book> wrapper = new UpdateWrapper<Book>().setSql("balance = balance -200").in("id", ids);//然后创建需要修改的对象属性User user = new User;user.setBalance(2000);bookDao.update(user,wrapper);}

2.2 自定义SQL

我们可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分

基本步骤:

  1. 基于Wrapper构建where条件
 @Testvoid testQueryWrappers(){List<Long> ids=List.of(1L,4L,2L);int mount = 200;//编写条件QueryWrapper<User> wrapper = new QueryWrapper<User>().in("id", ids);bookDao.updateIds(wrapper,mount);
  1. 在mapper方法参数中用Param注解声明wrapper变量名称,必须是ew
@Update("update tb_user set balance = balance - #{mount} ${ew.customSqlSegment}")
void updateIds(@Param("ew") QueryWrapper<User> wrapper,@Param("mount") int mount);

2.3 Service接口

利用的就是MybatisPlus创建好的IService<Book>ServiceImpl<BookDao, Book>两个父类,service和serviceImpl分别继承上述两个父类,就拥有了一系列MybaitisPlus封装好的方法

步骤:

  • 创建好BookService和 BookServiceImpl类,然后进行继承
@Service
public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements BookService {}
public interface BookService extends IService<Book> {
} 
  • 测试
 /** 用来测试service* */@Autowiredprivate BookService service;@Testvoid testService(){Book book = new Book();book.setName("大学英语");book.setDescription("学习英语成就背时人生!!!!");book.setType("四级英语");service.save(book);}/** 查询* */@Testvoid testServiceQuery(){List<Book> books = service.listByIds(List.of(15L, 16L, 22L));books.forEach(System.out::println);}

2.4 基于Restful风格实现下列小练习

在这里插入图片描述

  1. 新增用户
@Autowiredprivate AccountService accountService;/*增添用户*/@PostMappingpublic void InsertAccount(Account account){accountService.save(account);}
  1. 删除用户
@DeleteMapping("/{id}")public void DeleteAccount(@PathVariable Long id){accountService.removeById(id);}
  1. 根据ID查询用户
@GetMapping("/{id}")public Account QueryAccountById(@PathVariable Long id){return accountService.getById(id);}
  1. 根据IDS批量查询
@GetMappingpublic List<Account> QueryAccountByIds(@RequestParam("ids") List<Long> ids){return accountService.listByIds(ids);}
  1. 根据Id扣减余额

Controller中的代码:

 @PutMapping("/{id}/deduction/{money}")public void deductionMoneyById(@PathVariable Long id ,@PathVariable Long money){accountService.deductionMoney(id,money);}

AccountService中的代码:

public interface AccountService extends IService<Account> {void deductionMoney(Long id, Long money);
}

AccountServiceImpl当中的代码:

 public void deductionMoney(Long id, Long money) {//查询用户Account account = this.getById(id);//验证用户信息if (account == null || account.getStatus() == 0){//代表的是不能进行减去操作throw new RuntimeException("用户不存在或账户冻结");}//查询是否金额能够减去if(account.getMoney() < money ){throw new RuntimeException("用户的余额不足");}//进行金额消减baseMapper.deductionMoneyById(id,money);}

AccountDao当中的代码:

@Mapper
public interface AccountDao extends BaseMapper<Account> { @Update("update tbl_account set money = money - #{money} where id = #{id};")void deductionMoneyById(@Param("id") Long id,@Param("money") Long money); 
}

2.5 IService的Lambda查询

在这里插入图片描述

/*lambda查询用户,Condition是利用一个类来接收传输过来的数据*/@GetMapping("/list")public List<Account> QueryAccountLambda(Condition condition){List<Account> accounts = accountService.lambdaQuerys(condition.getUsername(),condition.getStatus(),condition.getMaxBalance(),condition.getMinBalance());return accounts;}
@Overridepublic List<Account> lambdaQuerys(@Param("username") String username,@Param("status") Integer status,@Param("maxBalance") Long maxBalance,@Param("minBalance") Long minBalance){return lambdaQuery().eq(username != null,Account::getUsername, username).eq(status != null ,Account::getStatus, status).le(maxBalance!= null,Account::getMoney, maxBalance).ge(minBalance!= null,Account::getMoney, minBalance).list();}

在这里插入图片描述
在Service当中实现的逻辑处理:

 @Overridepublic void deductionMoney(Long id, Long money) {//查询用户Account account = this.getById(id);//验证用户信息if (account == null || account.getStatus() == 0){//代表的是不能进行减去操作throw new RuntimeException("用户不存在或账户冻结");}//查询是否金额能够减去if(account.getMoney() < money ){throw new RuntimeException("用户的余额不足");}//进行金额消减long deMoney = account.getMoney() - money;System.out.println(deMoney);lambdaUpdate().set(Account::getMoney,deMoney).set(deMoney == 0,Account::getStatus,0).eq(Account::getId,id).eq(Account::getMoney,account.getMoney()) //乐观锁,防止多线程并发问题.update(); //必须要进行更新操作}

2.6 批量删除

在这里插入图片描述

 @Autowiredprivate AccountService service;/*首先创建一个自动增加的数据*/private Account buildAccount(int i){Account account = new Account();account.setMoney(2000+i);account.setStatus(1);account.setUsername("zhangsan" + i);return account;}@Testvoid InsertIds() {//首先创建一个容量为1000的list容器List<Account> list = new ArrayList<>(1000);//记录下当前时间long now = System.currentTimeMillis();for (int i = 0; i < 10000; i++) {list.add(buildAccount(i));//判断是否存满if (i%1000 == 0){//已经存满,加载数据service.saveBatch(list);//将list数据清空list.clear();}}long after = System.currentTimeMillis();System.out.println("总共用时:"+(after-now));}

在Datasource的url当中&这个参数:
在这里插入图片描述

三、拓展业务

下载插件IDEA当中的MybatisPlus

在这里插入图片描述
下载完后就点击这个进行Datasource的配置
在这里插入图片描述

在这里插入图片描述

点击这个进行配置文件的放置

在这里插入图片描述
在这里插入图片描述

3.1 静态工具

在这里插入图片描述
出现静态工具的原因是:
以为如果使用的是service进行创作,如果两张表相互嵌套相互使用,就会出现循环依赖,为了去除这个循环依赖,所以引入了静态工具

在这里插入图片描述

 Db.lambdaQuery(Account.class).eq(Account::getId, id).list()

3.2 逻辑删除

  • 逻辑删除就是基于代码逻辑模拟删除效果,但并不会真正删除数据。思路如下
    • 在表中添加一个字段标记数据是否被删除
    • 当删除数据时把标记置为1
    • 查询时只查询标记为0的数据

MybatisPlus提供了逻辑删除功能,无需改变方法调用的方式,而是在底层帮我们自动修改CRUD的语句。我们要做的就是在application.yaml文件中配置逻辑删除的字段名称和值即可:

mybatis-plus:global-config:db-config: logic-delete-field: deleted# 全局逻辑删除的实体字名,字段类型可以是boolean、integerlogic-delete-value: 1 # 逻辑已删除值(默认为 1)logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

就是说明我们在进行delete删除数据的时候不再是进行数据的删除,只是把deleted修改为1,在查询的时候加上where条件进行查询是否是1,如果为1,就不会在页面当中显示出来

逻辑删除的弊端:

  • 逻辑删除本身也有自己的问题,比如:会导致数据库表垃圾数据越来越多,影响查询效率
  • SQL中全都需要对逻辑删除字段做判断,影响查询效率因此,我不太推荐采用逻辑删除功能,
  • 如果数据不能删除,可以采用把数据迁移到其它表的办法

3.3、枚举处理器

步骤:

  1. 给枚举中的与数据库对应value值添加@EnumValue注解

  2. 在配置文件中配置统一的枚举处理器,实现类型转换


public enum SexEnum {MAN(1, "男"),WOMAN(2, "女");@EnumValueprivate Integer key;@JsonValueprivate String display;SexEnum(Integer key, String display) {this.key = key;this.display = display;}public Integer getKey() {return key;}public String getDisplay() {return display;}
}

3.4 JSON处理器

将数据库当中的JSON类型的String进行转换:

在这里插入图片描述

  • 步骤:
    在这里插入图片描述
    在这里插入图片描述

3.5 分页插件功能

  1. 首先创建一个配置配去配置拦截器
@Configuration
public class MyBatisConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();//1. 创建分页条件PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);//2.将分页的条件放入到拦截器当中interceptor.addInnerInterceptor(paginationInnerInterceptor);return interceptor;}
}
  1. 调用方法,把条件插入
 /*测试分页工具*/@Testvoid testPage(){//给与条件int pageNum = 1;int pageSize = 1;Page<Book> page = Page.of(pageNum, pageSize);//添加排序条件,可以添加多个,如果前一个相同,就按照后面的进行操作page.addOrder(new OrderItem("id", true));Page<Book> p =  service.page(page);  //可以查询表的其他信息 //获取到查询数据的总条数long total = p.getTotal();System.out.println("total"+total);//获取到当前分页的全部数据List<Book> records = p.getRecords();records.forEach(System.out::println);//获取到页码的数量long pages = p.getPages();System.out.println("pages:"+pages);}

3.6 通用分页实体

pojo.Book层:

@Data
@TableName("tbl_book")
public class Book {private Integer id;private String type;private String name;private String description;
}

PageInfo(就是封装的分页信息类):

@Data
public class PageInfo<T> {/*查询到的总条数*/private Long total;/*查询到的总页数*/private Long pages;/*查询到当前页的所有数据*/private List<T> info;
}

MybatisConfig(注解封装的拦截器,用来拦截信息添加分页功能):

@Configuration
@MapperScan("com.itheima.dao")
public class MyBatisConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();//1. 创建分页条件PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);//2.将分页的条件放入到拦截器当中interceptor.addInnerInterceptor(paginationInnerInterceptor);return interceptor;}
}

BookController:

@RestController
@RequestMapping("/books")
public class BookController {@Autowiredprivate BookService service;@GetMapping("/pages")PageInfo<Book> myQueryPages(BookQuery bookQuery){return service.QueryPages(bookQuery);} 
}

BookDao:

@Mapper
public interface BookDao extends BaseMapper<Book>{@Select("select * from tbl_book where id > #{id}")Page<Book> selectPageVo(@Param("page") Page<User> page, @Param("id") Integer id);
}

TemplateQuery(查询条件类的模板《父类》):

@Data
public class TemplateQuery {//页码private int queryPage;//sizeprivate int querySize;//排序条件private String ordered;//升序还是降序(true升序)private boolean desc;
}

BookQuery(创建放置查询条件的类):

@Data
public class BookQuery extends TemplateQuery{/*查询的书名字*/private String name;/*查询的科目*/private String type;
}

Bookservice:

public interface BookService extends IService<Book> {PageInfo<Book> QueryPages(BookQuery bookQuery);
} 

BookServiceImpl:

@Service
public class BookServiceImpl extends ServiceImpl<BookDao, Book> implements BookService {@Overridepublic PageInfo<Book> QueryPages(BookQuery bookQuery) {//获取到传输过来的数据int queryPage = bookQuery.getQueryPage();String name = bookQuery.getName();int querySize = bookQuery.getQuerySize();String ordered = bookQuery.getOrdered();String type = bookQuery.getType();//分页查询条件Page<Book> page = Page.of(queryPage, querySize);//排序条件//进行判断if(ordered != null){page.addOrder(new OrderItem(ordered,bookQuery.isDesc()));}else {//设置默认值page.addOrder(new OrderItem("id",true));}//分页条件lambdaQuery().like(name !=null,Book::getName,name).like(type != null,Book::getType,type).page(page);//将数据进行封装PageInfo<Book> bookPageInfo = new PageInfo<>();bookPageInfo.setPages(page.getPages());bookPageInfo.setInfo(page.getRecords());bookPageInfo.setTotal(page.getTotal());return bookPageInfo;}
}

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

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

相关文章

freeRTOS学习day4-中断使用消息队列

首先设置好中断优先级 看freeRTOS配置文件 freeRTOS可以管理的优先级范围是5-15 所以开始我把子优先级设置为4 会卡死在发送那里 https://www.cnblogs.com/realiot/articles/16699272.html 另外一点 一定要设置中断优先级分组 忘了设置也会卡死 void USART1_IRQHandler(vo…

Java中的volatile关键字

volatile是什么&#xff1f; "volatile"是一个关键字&#xff0c;用于修饰变量。它的作用是告诉编译器该变量可能会在意料之外的时候被修改&#xff0c;因此编译器在对该变量进行优化时需要特别小心。 具体来说&#xff0c;当一个变量被声明为"volatile"…

IDEA 2023.2.2 使用 Scala 编译报错 No scalac found to compile scala sources

一、问题 scala: No scalac found to compile scala sources 官网 Bug 链接 二、临时解决方案 Incrementality Type 先变成 IDEA 类型 Please go to Settings > Build, Execution, Deployment > Compiler > Scala Compiler and change the Incrementality type to …

[已解决]安装的明明是pytorch-gpu,但是condalist却显示cpu版本,而且torch.cuda.is_available 也是flase

问题; 安装了gpu版本的pytorch&#xff0c;但是显示的torch.cuda.is_available(&#xff09;却是flase。 conda list查看 版本显示只有cpuonly 在网上找了半天&#xff0c;也没有解决办法。 仔细看了一下&#xff0c;发现&#xff0c;有个单独的包叫cpuonly&#xff0c;不知道…

JS问题:如何实现文本一键复制和长按复制功能?

前端功能问题系列文章&#xff0c;点击上方合集↑ 序言 大家好&#xff0c;我是大澈&#xff01; 本文约2000字&#xff0c;整篇阅读大约需要4分钟。 本文主要内容分三部分&#xff0c;第一部分是需求分析&#xff0c;第二部分是实现步骤&#xff0c;第三部分是问题详解。 …

033-第三代软件开发-固定区域截图

第三代软件开发-固定区域截图 文章目录 第三代软件开发-固定区域截图项目介绍固定区域截图QWidget 版本QML 版本 自由截图自由截图二 关键字&#xff1a; Qt、 Qml、 关键字3、 关键字4、 关键字5 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QM…

js实现将文本生成二维码(腾讯云cos)

示例 页面代码 import { getQCodeUrl } from /utils/cosInstance; import { PageContainer } from ant-design/pro-components; import { Access, useAccess } from umijs/max; import { Button, Image } from antd; import { useState } from react;const AccessPage: Reac…

AD7321代码SPI接口模数转换连接DAC0832输出verilog

名称&#xff1a;AD7321代码12位ADC&#xff0c;SPI接口模数转换连接DAC0832输出 软件&#xff1a;QuartusII 语言&#xff1a;VHDL 代码功能&#xff1a; 使用VHDL语言编写代码&#xff0c;实现AD7321的控制&#xff0c;将模拟信号转换为数字信号&#xff0c;再经过处理后…

SpringCore完整学习教程5,入门级别

本章从第6章开始 6. JSON Spring Boot提供了三个JSON映射库的集成: Gson Jackson JSON-B Jackson是首选的和默认的库。 6.1. Jackson 为Jackson提供了自动配置&#xff0c;Jackson是spring-boot-starter-json的一部分。当Jackson在类路径上时&#xff0c;将自动配置Obj…

vue3-admin-element框架登录如何修改?

1、找到vite.config.js文件 配置反向代理 2、找到src文件下的user.js文件 3、找到views文件下的login文件 打开找到comp文件夹找到LoginFrom.vue页面进去 把这个改成自己的账户数据&#xff08;密码不一致自行更改&#xff09; 4、找到store文件下的modules下的user.js 5、找到…

安装 tensorflow==1.15.2 遇见的问题

一、直接安装 命令&#xff1a;pip install tensorflow1.15.2 二、换 阿里云 镜像源 命令&#xff1a;pip install -i http://mirrors.aliyun.com/pypi/simple tensorflow1.15.2 三、换 豆瓣 镜像源 命令&#xff1a;pip install http://pypi.douban.com/simple tensorflow1…

vscode连接服务器一直retry

解决方法 打开vscode控制面板&#xff0c;输入命令remote-ssh: kill vs code server on host 选择一直连接不上的服务器端口 重新连接

Mysql第四篇---数据库索引优化与查询优化

文章目录 数据库索引优化与查询优化索引失效案例数据准备1. 全值匹配2 最佳左前缀法则(联合索引)主键插入顺序4 计算、函数导致索引失效5 类型转换(自动或手动)导致索引失效6 范围条件右边的列索引失效7 不等于(!或者<>)索引失效8 is null可以使用索引, is not null无法使…

C++入门精讲——入门看完这一篇就够了

文章目录 前言1. C发展历史2. 关键字3. 命名空间3.1 命名空间的概念3.2 命名空间的定义3.3 命名空间的使用 4. C输入、输出5. 缺省参数5.1 全缺省5.2 半缺省 6. 函数重载6.1 几种不同类型的函数重载6.2 函数重载的原理——名字修饰(name Mangling)6.2.1 C程序为什么不支持函数重…

一文解决:Swagger API 未授权访问漏洞问题

Swagger 是一个用于设计、构建、文档化和使用 RESTful 风格的 Web 服务的开源软件框架。它通过提供一个交互式文档页面&#xff0c;让开发者可以更方便地查看和测试 API 接口。然而&#xff0c;在一些情况下&#xff0c;未经授权的访问可能会导致安全漏洞。本文将介绍如何解决 …

ESP8266,手机与电脑之间的TCP通讯

电脑端运行通讯猫调试助手,作为服务端: 电脑端 电脑的IP地址是: 192.168.2.232 手机与电脑之间的TCP通讯 手机端运行网络调试精灵,作为客户端: 手机端 如果从手机端点击"发送"按钮,则也会将"ghhh东方红广场"几个字发送到电脑上(服务端). ESP8266作为客户…

H5游戏分享-全民找房祖名qmxzfzm

H5游戏分享-全民找房祖名qmxzfzm 一开始就比较简单 后面就会越来越难&#xff0c;而且也有时间限制 游戏的源码 <!DOCTYPE html> <html><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,ini…

【AD9361 数字接口CMOS LVDSSPI】B 并行数据之CMOS 续

续【AD9361 数字接口CMOS &LVDS&SPI】B 并行数据之CMOS 数据总线空闲和周转周期 &#xff08;CMOS&#xff09; P0_D[11&#xff1a;0]和P1_D[11&#xff1a;0]总线信号通常由BBP或AD9361有源驱动。在任何空闲期间&#xff0c;两个组件都会忽略数据总线值。但是&…

【Unity3D】Unity与Android交互

1 Unity 发布 apk 1.1 安装 Android Build Support 在 Unity Hub 中打开添加模块窗口&#xff0c;操作如下。 选择 Android Build Support 安装&#xff0c;如下&#xff08;笔者这里已安装过&#xff09;。 创建一个 Unity 项目&#xff0c;依次点击【File→Build Settings→…

Pytorch从零开始实战07

Pytorch从零开始实战——咖啡豆识别 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——咖啡豆识别环境准备数据集模型选择训练模型可视化模型预测其他问题总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c;Pytor…