26届JAVA 学习日记——Day8

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事务中有哪几种事务传播行为?

事务传播行为是为了解决业务层方法之间互相调用的事务问题。

  1. TransactionDefinition.PROPAGATION_REQUIRED
    使用的最多的一个事务传播行为,我们平时经常使用的@Transactional注解默认使用就是这个事务传播行为。如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  2. TransactionDefinition.PROPAGATION_REQUIRES_NEW
    创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
  3. TransactionDefinition.PROPAGATION_NESTED
@Transactional(propagation = Propagation.NESTED)
public void doWork() {
    // 这里是嵌套事务的逻辑
}

如果doWork()方法在一个已经存在的事务中被调用,它将在当前事务中创建一个嵌套事务。如果 doWork() 方法抛出异常,可以选择回滚到嵌套事务的保存点,而不是回滚整个外部事务;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED(即新建一个事务)。

  1. 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()方法直接获取记录总数和内容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值