2024.11.12 周二
距离上次打卡已经过去了三天,虽然有三天没有学习,但是旅游的过程还是很治愈的。今天开始继续打卡。
八股
SpringBoot里面有哪些重要的注解?有一个配置相关的注解是哪个?
- @SpringBootApplicaiton:用于标注主应用程序类,标识一个Spring Boot应用程序的入口点,同时启用自动配置和组件扫描。
@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@Slf4j
public class SkyApplication {
public static void main(String[] args) {
SpringApplication.run(SkyApplication.class, args);
log.info("server started");
}
}
- @Controller(通常
@RestController
):标识控制器类,处理HTTP请求。 - @RestController:结合@Controller和@ResponseBody,返回RESTful风格的数据。
- @Service:标识服务类,通常用于标记业务逻辑层。
- @Repository(通常
@Mapper
):标识数据访问组件,通常用于标记数据访问层。 - @Component:通用的Spring组件注解,表示一个受Spring管理的组件。
- @Autowired:用于自动装配Spring Bean。
- @Value:用于注入配置属性值。
@Component
public class ExampleBean {
@Value("${example.property}")
private String propertyValue;
// ... 使用 propertyValue(example.property)
@Value("${JAVA_HOME}")
private String javaHome;
// ... 使用 javaHome(环境变量)
}
-
@RequestMapping:用于映射HTTP请求路径到Controller的处理方法。
-
@GetMapping、@PostMapping、@PutMapping、@DeleteMapping:简化@RequestMapping的GET、POST、PUT和DELETE请求。
-
@Configuration:用于指定一个类为配置类,其中定义的bean会被Spring容器管理。通常与@Bean配合使用,@Bean用于声明一个Bean实例,由Spring容器进行管理。
//此处指定OssConfiguration为配置类,其中@Bean声明的AliOssUtil被Spring容器管理
@Configuration
@Slf4j
public class OssConfiguration {
@Bean
@ConditionalOnMissingBean //条件注解-确保只有在Spring容器中不存在该类Bean时才会创建Bean
public AliOssUtil ossUtil(AliOssProperties aliOssProperties){
log.info("开始创建阿里云文件上传工具类对象:{}",aliOssProperties);
return new AliOssUtil(aliOssProperties.getEndpoint(),
aliOssProperties.getAccessKeyId(),
aliOssProperties.getAccessKeySecret(),
aliOssProperties.getBucketName());
}
}
Spring管理事务的方法有哪些?
- 编程式事务:在代码中硬编码(在分布式系统中推荐使用) : 通过 TransactionTemplate或者 TransactionManager 手动管理事务,事务范围过大会出现事务未提交导致超时,因此事务要比锁的粒度更小。
- 声明式事务:在 XML 配置文件中配置或者直接基于注解(单体应用或者简单业务系统推荐使用) : 实际是通过 AOP 实现(基于
@Transactional
的全注解方式使用最多)
@Override
@Transactional
/**
此处通过@Transactional全注解保证实现类中的该方法需作为事务整体执行
否则将回滚,由此保证菜品表和对应口味表的一致性。
*/
public void saveWithFlavor(DishDTO dishDTO) {
// 将接收的的dishDTO对象拆分成两个bean对象
Dish dish = new Dish();
BeanUtils.copyProperties(dishDTO, dish);
// 向菜品表插入1条数据
dishMapper.insert(dish);
// 获取insert语句生成的主键值
Long dishId = dish.getId();
List<DishFlavor> flavors = dishDTO.getFlavors();
if (flavors != null && flavors.size() > 0){
flavors.forEach(dishFlavor -> {
dishFlavor.setDishId(dishId);
});
// 向口味表插入n条数据
dishFlavorMapper.insertBatch(flavors);
}
}
Spring事务中有哪几种事务传播行为?
事务传播行为是为了解决业务层方法之间互相调用的事务问题。
TransactionDefinition.PROPAGATION_REQUIRED
使用的最多的一个事务传播行为,我们平时经常使用的@Transactional注解默认使用就是这个事务传播行为。如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。TransactionDefinition.PROPAGATION_REQUIRES_NEW
创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。TransactionDefinition.PROPAGATION_NESTED
@Transactional(propagation = Propagation.NESTED)
public void doWork() {
// 这里是嵌套事务的逻辑
}
如果doWork()
方法在一个已经存在的事务中被调用,它将在当前事务中创建一个嵌套事务。如果 doWork()
方法抛出异常,可以选择回滚到嵌套事务的保存点,而不是回滚整个外部事务;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED
(即新建一个事务)。
TransactionDefinition.PROPAGATION_MANDATORY
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)这个使用的很少。
算法
199.二叉树的右视图(哈希表+栈)
15.三数之和
项目
苍穹外卖项目进度
该代码是如何处理flavors的?
/**
* 根据id修改菜品基本信息和对应的口味信息
* @param dishDTO
*/
@Override
public void updateWithFlavor(DishDTO dishDTO) {
Dish dish = new Dish();
BeanUtils.copyProperties(dishDTO,dish);
//修改菜品表基本信息
dishMapper.update(dish);
//删除原有的口味数据
dishFlavorMapper.deleteByDishId(dishDTO.getId());
//重新插入口味数据
//获取List<DishFlavor>对象flavors
List<DishFlavor> flavors = dishDTO.getFlavors();
//如果flavors不为空,且其长度大于0
if (flavors != null && flavors.size() > 0){
//对列表调用forEach方法,并在其中通过lambda表达式进行操作
/**
dishFlavor -> { dishFlavor.setDishId(dishDTO.getId()); }
是一个Lambda表达式,它代表了一个没有参数名称的函数
该函数接受一个DishFlavor类型的参数,并执行一个操作(设置dishId属性)。
*/
flavors.forEach(dishFlavor -> {
dishFlavor.setDishId(dishDTO.getId());
});
//向口味表插入n条数据
dishFlavorMapper.insertBatch(flavors);
}
}
useGeneratedKeys
是什么?
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into dish (name, category_id, price, image, description, create_time, update_time, create_user,update_user, status)
values (#{name}, #{categoryId}, #{price}, #{image}, #{description}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser}, #{status})
</insert>
useGeneratedKeys="true"
告诉 MyBatis 这个插入操作会生成一个键。
keyProperty="id"
指定了应该将生成的键赋值给 Dish 类的 id 属性。
id
作为一个非空约束、自增约束的主键,在此处useGeneratedKeys="true"
和keyProperty="id"
告诉数据库在创建的时候应该自动生成id
通过插件实现分页查询的逻辑
/**
* 分页查询
* @param categoryPageQueryDTO
* @return
*/
public PageResult pageQuery(CategoryPageQueryDTO categoryPageQueryDTO) {
PageHelper.startPage(categoryPageQueryDTO.getPage(),categoryPageQueryDTO.getPageSize());
//下一条sql进行分页,自动加入limit关键字分页
Page<Category> page = categoryMapper.pageQuery(categoryPageQueryDTO);
return new PageResult(page.getTotal(), page.getResult());
}
根据Api文档,通过PageHelper实现分页查询的逻辑如下:
PageHelper.startPage()
方法中传入第几页
页数大小
- 通过
Page<?>
类封装每页中显示的Java实体类 - 通过Page类提供的
getTotal()
和getResult()
方法直接获取记录总数和内容