IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 学习记录tips -> 正文阅读

[Java知识库]学习记录tips

1、Lombok 的 @Builder 注解

@Builder 注释为类生成相对略微复杂的构建器API。@Builder 可以让你以下面显示的那样调用你的代码,来初始化实例对象:

Student.builder()
               .sno( "001" )
               .sname( "admin" )
               .sage( 18 )
               .sphone( "110" )
               .build();

我们在对实体对象进行操作时,往往会存在对某些实体对象的某个字段进行二次赋值。@Builder 注解里有个 toBuilder() 方法,使用 toBuilder() 可以实现以一个实例为基础继续创建一个对象,也就是重用原来对象的值。但是,这会创建一个新的对象,而不是原来的对象,原来的对象属性是不可变的,除非你自己想要给这个实体类再添加上 @Data 或者 @Setter 方法。

转载自:详解Lombok中的@Builder用法

2、Lombok 的 @Accessors 注解

(1)该注解主要作用是:当属性字段在生成 getter 和 setter 方法时,做一些相关的设置。

(2)当它可作用于类上时,修饰类中所有字段,当作用于具体字段时,只对该字段有效。

该字段共有三个属性,分别是 fluent,chain,prefix。

2.1 fluent 属性

不写默认为false,当该值为 true 时,对应字段的 getter 方法前面就没有 get,setter 方法就不会有 set。

在这里插入图片描述

2.2 chain 属性

不写默认为false,当该值为 true 时,对应字段的 setter 方法调用后,会返回当前对象。

在这里插入图片描述

2.3 prefix 属性

该属性是一个字符串数组,当该数组有值时,表示忽略字段中对应的前缀,生成对应的 getter 和 setter 方法。

比如现在有 xxName 字段和 yyAge 字段,xx 和 yy 分别是 name 字段和 age 字段的前缀。

那么,我们在生成的 getter 和 setter 方法如下,它也是带有 xx 和 yy 前缀的。

在这里插入图片描述

如果,我们把它的前缀加到 @Accessors 的属性值中,则可以像没有前缀那样,去调用字段的 getter和 setter 方法。

在这里插入图片描述
转载自:@Accessors 注解详解

3、CharSequence

CharSequence 在 java.lang 包下,是一个描述字符串结构的接口,表示 char 值的一个可读序列。此接口对许多不同种类的 char 序列提供统一的自读访问。此接口不修改 equals 和 hashCode 方法的常规协定,因此,通常未定义比较实现 CharSequence 的两个对象的结果。他有几个实现类:CharBuffer、String、StringBuffer、StringBuilder。

在这里插入图片描述
CharSequence 与 String 都能用于定义字符串,但 CharSequence 的值是可读可写序列,而 String 的值是只读序列。
对于抽象类或者接口来说不可以直接使用new的方式创建对象,但是可以直接给它赋值进行实例的创建:

CharSequence cs="hello";

参考自:CharSequence详情介绍

4、springboot 参数校验

实际业务开发中,为了避免入参错误对业务系统有影响,一般会都会在Controller层进行参数校验,常见的方式主要包含了两种:

get、delete等请求,参数形式为RequestParam/PathVariable
post、put等请求,参数形式为RequestBoty
RequestParam/PathVariable形式的参数校验
Get、Delete请求一般会使用RequestParam/PathVariable形式参数参数,这种形式的参数校验一般需要以下两个步骤,如果校验失败,会抛出ConstraintViolationException异常。

必须在Controller类上标注@Validated注解;
在接口参数前声明约束注解(如@NotBlank等)

@Validated
@RestController
@RequestMapping("/validate")
public class ValidationController {
    private Logger log = LoggerFactory.getLogger(ValidationController.class);

    /**
     * get、delete请求使用requestParam/PathVariable形式传递参数的,
     * 参数校验需要在Controller添加上@Validated注解,并在参数列表中添加对应的校验注解即可
     *
     * @param id ID
     * @return true/false 成功或失败
     */
    @GetMapping("/get")
    public ResultObject<Boolean> validateGetRequest(@NotBlank(message = "id不能为空") String id,
                                                    @NotBlank(message = "appkey不能为空") String appkey) {
		// 具体业务逻辑调用
        log.info("id [{}] appKey [{}]", id, appkey);
        return ResultObject.success();
    }
}

转载自:springboot 参数校验

5、Mybatis 方法单个参数

正常情况下,mybatis 在进行参数判断的时候,直接用就可以了,使用 entity 实体或者 Map 的时候,下面的代码是正确的:
在这里插入图片描述
是单个参数和多参数的判断有个不同点,当我们的入参为 entity 实体,或者 map 的时候,使用 if 参数判断没任何问题。但是当我们的入参为 java.lang.Integer 或者 java.lang.String 的时候,这时候就需要注意一些事情了。

我们需要使用 if 参数判断 引入参数,会抛异常 nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named ‘deptId’ in ‘class java.lang.String’

<select id="queryList" resultType="com.soft.back.model.OutdevFactory"
			parameterType="java.lang.String">
	select
	    <include refid="Base_Column_List"/>
	from op_outdev_factory
	<where>
	    <if test="factoryName != null">
		and name like concat('%',#{factoryName},'%')
	    </if>
	</where>
</select>

原因就是对于这类单个入参然后用 if 判断的,mybatis 有自己的内置对象,Mybatis 默认采用 OGNL 解析参数,所以会自动采用对象树的形式取 string.xxx 值,如果没在方法中定义,则会抛异常报错。

解决方案:

方案一:把 #{xxx} 修改为 #{_parameter}

<select id="queryList" resultType="com.soft.back.model.OutdevFactory"
			parameterType="java.lang.String">
	select
	    <include refid="Base_Column_List"/>
	from op_outdev_factory
	<where>
	    <if test="_parameter != null">
		and name like concat('%',#{_parameter},'%')
	    </if>
	</where>
</select>

方案二:在方法中提前定义

/**
 * 查询厂家列表
 * @param factoryName
 * @return
 */
List<OutdevFactory> getFactoryList(@Param("factoryName") String factoryName);
<select id="queryList" resultType="com.soft.back.model.OutdevFactory"
			parameterType="java.lang.String">
	select
	    <include refid="Base_Column_List"/>
	from op_outdev_factory
	<where>
	    <if test="factoryName!= null">
		and name like concat('%',#{factoryName},'%')
	    </if>
	</where>
</select>

转载自:【Mybatis异常】nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter

6、@Configuration 注解

@Configuration,功能:将想要的组件添加到容器中。使用注解 @Configuration,告诉Spring Boot这是一个配置类。
在类里边使用 @bean 注解。@bean:给容器中添加组件,以方法名作为组件的id。返回类型为组件类型,返回的值,就是组件在容器中的实例。

在Spring Boot 5.2之后的@Configuration注解多了一个属性proxyBeanMethods,默认为true(翻译:代理bean的方法)
为true了,也就是默认代理。代理就会保持组件的单实例。

也就是说,虽然写的配置类是在容器中注册组件用的,但是在注册组件之前会在容器中查找有没有该组件。如果有,则取该组件用于保证单实例,如果没有再注册一个新的组件。

如果将@Configuration(proxyBeanMethods = true)改为false,每一个方法都会新注册一个组件,改为false后久不会再保存代理对象了。

proxyBeanMethods:代理bean的方法
有两种模式:

(1)Full:(proxyBeanMethods = true) //全模式
使用代理模式,保证组件的单实例,启动不如false快,但是重复利用率高,适用于会重复使用组件的场景。

(2)lite:(proxyBeanMethods = false) //轻量级
不是用代理模式,不用保证组件的单实例,启动最快。单每次调用组件都会重新创建一个新的组件,组件可重复使用率低。适用于需要组件但不会重复使用的场景

总结:用于解决组件依赖

转载自:@Configuration详解

7、Assert工具类

从JDK1.4版本开始,Java语言引入了断言(assert)机制。该类在 package org.springframework.util 包下。

断言常用的方法:

(1)notNull(Object object)当 object 为 null 时抛出异常,notNull(Object object, String message) 方法允许通过 message 定制异常信息。和 notNull() 方法断言规则相反的方法是 isNull(Object object) / isNull(Object object, String message),它要求入参一定是 null;

(2)isTrue(boolean expression) / isTrue(boolean expression, String message)当 expression 不为 true 抛出异常;

(3)notEmpty(Collection collection) / notEmpty(Collection collection, String message)当集合未包含元素时抛出异常。

notEmpty(Map map) / notEmpty(Map map, String message) 和 notEmpty(Object[] array, String message) / notEmpty(Object[] array, String message) 分别对 Map 和 Object[] 类型的入参进行判断;

转载自:Spring中Assert工具类的用法

8、Optional类

Optional类主要解决空指针异常NullPointerException。
Optional 类(java.util.Optional)是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。

创建Optional 对象

声明一个空的Optional:
通过静态工厂方法Optional.empty(),创建一个空的Optional 对象,Optional中只有私有的构造方法,所以只能在其类中查找已经提供的创建方法。

public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

Optional<Car> optCar = Optional.empty(); 

依据一个非空值创建Optional:
使用静态工厂方法Optional.of(T),依据一个非空值创建一个Optional对象:

public static <T> Optional<T> of(T value) {
    return new Optional<>(value);
}

Optional<String> optCar = Optional.of("sdfs");

由于这种方法创建时,会new Optional(T t),而在new的过程中,私有的构造函数对其传入的变量有检验:

private Optional(T value) {
        this.value = Objects.requireNonNull(value);
}

当传入的参数为 null 时会爆 NullPointerException
在这里插入图片描述

转载自:java8中的Optional

9、LocalDate类的plusDays()方法

plusDays() 方法用于将以天为单位的给定持续时间添加到此 LocalDate 并返回 LocalDate。此方法是一个非静态方法,只能通过类对象访问,如果尝试使用类名访问该方法,则会收到错误消息。

例子:

// Java program to demonstrate the example 
// of plusDays(long day_val) method of LocalDate

import java.time.*;
 
public class PlusDaysOfLocalDate {
    public static void main(String args[]) {
        long days = 10;
        // Instantiates two LocalDate
        LocalDate l_da1 = LocalDate.parse("2007-04-04");
        LocalDate l_da2 = LocalDate.of(2008, Month.FEBRUARY, 06);
 
        // Display l_da1,l_da2 and days
        System.out.println("LocalDate l_da1,l_da2 : ");
        System.out.println("l_da1: " + l_da1);
        System.out.println("l_da2: " + l_da2);
        System.out.println("days to add: " + days);
 
        System.out.println();
 
        // Here, this method adds the given
        // days to this date l_da1
        // i.e. here we are adding 10
        // days to the date l_da1
        LocalDate plus_days = l_da1.plusDays(days);
 
        // Display plus_days
        System.out.println("l_da1.plusDays(days): " + plus_days);
 
        // Here, this method adds the given
        // days to this date l_da2
        // i.e. here we are adding 10
        // days to the date l_da2
        plus_days = l_da2.plusDays(days);
 
        // Display plus_days
        System.out.println("l_da2.plusDays(days): " + plus_days);
    }
}

输出结果:

LocalDate l_da1,l_da2 : 
l_da1: 2007-04-04
l_da2: 2008-02-06
days to add: 10
 
l_da1.plusDays(days): 2007-04-14
l_da2.plusDays(days): 2008-02-16

转载自:Java LocalDate类 | plusDays()方法与示例

10、Mybatis 报错 Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter

Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #2 wit

解决办法:把注释去掉

转载自:Mybatis 报错 Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter

11、Mybatis——foreach用法

foreach 元素的属性

(1)collection:要做 foreach 的对象,作为入参时,List<?> 对象默认用 list 代替作为键,数组对象有 array 代替作为键,Map 对象没有默认的键。
当然在作为入参时可以使用 @Param(“keyName”) 来设置键,设置 keyName 后,list、array 将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子:
如果 User 有属性 List ids。入参是 User 对象,那么这个 collection = “ids”
如果 User 有属性 Ids ids;其中 Ids 是个对象,Ids 有个属性 List id;入参是 User 对象,那么 collection = “ids.id”
上面只是举例,具体 collection 等于什么,就看你想对那个元素做循环。
该参数为必选。

(2)item: 循环体中的具体对象。支持属性的点路径访问,如item.age,item.info.details。
具体说明:在list和数组中是其中的对象,在map中是value。该参数为必选。

(3)index: 在list、array中,index为元素的序号索引。但是在Map中,index为遍历元素的key值,该参数为可选项;

(4)open: 遍历集合时的开始符号,通常与close=")"搭配使用。使用场景IN(),values()时,该参数为可选项;

(5)separator: 元素之间的分隔符,类比在IN()的时候,separator=“,”,最终所有遍历的元素将会以设定的(,)逗号符号隔开,该参数为可选项;

(6)close: 遍历集合时的结束符号,通常与open="("搭配使用,该参数为可选项;

如果传入的参数类型为 List 时,collection 的默认属性值为 list,同样可以使用 @Param 注解自定义 keyName。

示例:
Mapper接口定义的方法:UserList 为模拟返回的数据对象

List<UserList> getUserInfo(@Param("userName") List<String> userName);

Mapper.xml 动态 sql 构建,Mapper 接口的方法名和 xml 文件的 id 值,必须一一对应,否则会报错:
-----建议做 if test="xxxx !=null and xxxx.size()>0"的校验,比较严谨。如果传入的参数类型为 array ,则校验为.length();

<select id="getUserInfo" resultType="com.test.UserList">
    SELECT
    *
    FROM user_info
    where
    <if test="userName!= null and userName.size() >0">
        USERNAME IN
        <foreach collection="userName" item="value" separator="," open="(" close=")">
            #{value}
        </foreach>
    </if>
</select>

使用默认属性值 list 作为 keyname:

对应的 Dao 中的 Mapper 文件是:

public List<User> selectByIds(List<Integer> userIds);

xml 文件代码片段:

<select id="selectByIds" resultType="com.olive.pojo.User">
    select * from t_user where id in
    <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
        #{item}
    </foreach>
</select>

转载自:1、Mybatis——foreach用法
2、mybatis for each循环详解

12、Spring 常用注解@Configuration,@Bean,@Component,@Service,@Controller,@Repository,@Entity的区分与学习

(1)@Component
作用于类上,相当于一个基类,跟 @Bean 一样,可以托管到Spring容器进行管理。

(2)@Service,@Controller,@Repository
作用于类上,={@Component + 一些特定的功能}。这些注解在部分功能上是一样的,但有一些细分:

@Controller注解类:SpringMVC 的理念,进行前端请求的处理,转发,重定向。包括调用Service层的方法。

@Service注解类:处理业务逻辑

@Repository注解类:作为 DAO 对象(数据访问对象,Data Access Objects),这些类可以直接对数据库进行操作。

(3)@Entity注解
作用于类上,数据表对应到实体类的映射。

(4)@Configuration
作用于类上,从 Spring3.0 开始,@Configuration 用于定义配置类,可替换 xml 配置文件,被注解的类内部包含有一个或多个被@Bean 注解的方法, 这些方法将会被 AnnotationConfigApplicationContext 或 AnnotationConfigWebApplicationContext 类进行扫描,并用于构建 bean 定义,初始化 Spring 容器。

(5)@Bean
标注在方法上,返回某个实例的方法,这个实例就会交给 Spring 容器管理。 此注解其实就等价于 spring 的 xml 配置文件中的,作用为:注册 bean 对象。 @Bean 一般是跟 @Configuration 一起用的相当于 < beans >< bean >< /bean >< /beans >。

转载自:Spring 常用注解@Configuration,@Bean,@Component,@Service,@Controller,@Repository,@Entity的区分与学习

13、sql的四种连接——左外连接、右外连接、内连接、全连接

(1)内连接
满足条件的记录才会出现在结果集中。

语法1select f1,f2,f3...
       from table1 inner join table2 
       on 关联匹配条件
语法2: select f1,f2,f3...
       from table1,table2,table3
       where 关联匹配条件

①自连接
概念:是内连接查询中一种特殊的等值连接,所谓的自连接就是指表与其自己当前表进行连接。自己和自己做连接。

②等值连接
就是在关键字 on 后的匹配条件是通过=来实现的;
自连接是一种特殊的等值连接。自连接是自己连接自己,等值连接通常是一个表连接另外一张表。

③不等值连接
在关键字 on 后匹配条件中使用除了=以外的关系运算符实现的不等条件(> >= < <= !=)

(2)左外连接(left outer join,outer 可省略)
左表全部出现在结果集中,若右表无对应记录,则相应字段为 NULL

(3)右外连接(right outer join,outer 可省略)
右表全部出现在结果集中,若左表无对应记录,则相应字段为 NULL

(4)全连接(full outer join,outer 可省略)
全外连接 = 左外连接 + 右外连接

转载自:1、sql的四种连接——左外连接、右外连接、内连接、全连接
2、MySQL–内连接查询(inner join)

14、mybatis 中的<![CDATA[ ]]>用法及说明

(1)平时在 mybatis 的映射文件写 sql 时,很多时候都需要写一些特殊的字符。例如:“<” 字符 “>” 字符 “>=” 字符 “<=” 字符,但是在 xml 文件中并不能直接写上述列举的字符,否则就会报错。

(2)因为在解析 xml 文件时候,我们如果书写了特殊字符,在没有特殊处理的情况下。这些字符会被转义,但我们并不希望它被转义,所以我们要使用 <![CDATA[ ]]> 来解决。

(3)那为什么要这样书写呢?<![CDATA[ ]]> ,不言而喻:这是 XML 语法。在 CDATA 内部的所有内容都会被解析器忽略(在该标签中的语句和字符原本是什么样的,在拼接成 SQL 后还是什么样的)。

(4)所以,当我们在 xml 文本中包含了很多的 “<” 字符 “<=” 和 “&” 字符—就像程序代码一样,那么最好把他们都放到 CDATA 部件中。

注意:
(1)使用动态 SQL 时要像 if、foreach、where 等标签一但被 <![CDATA[ ]]> 标签包裹,将忽略 xml 的解析并出错
(2)<![CDATA[ ]]> 标签中不可嵌套 <![CDATA[ ]]> 标签
(3)<![CDATA[ ]]> 尽量缩小范围,以免出错

转载自:1、CDATA[]的简单使用
2、mybatis 中的CDATA[]用法

15、parallelStream() 并行流操作

这是流编程,stream() 是串行操作的。但是 parallelStream() 恰恰相反,是并行操作的,两者的执行效率的话肯定是 parallelStream() 要快,毕竟是多线程的,但是这就就会涉及到线程安全的问题了,一旦涉及到线程安全的问题,那些线程不安全的集合类型都不能用,像 HashMap、ArrayList 都不能用,只能用线程安全的集合。

转载自:parallelStream()并行流操作

16、Stream流的用法

steam():把一个源数据,可以是集合,数组,I/O channel, 产生器 generator 等,转化成流。

forEach():迭代流中的每个数据。以下代码片段使用 forEach 输出了10个随机数。

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

map():用于映射每个元素到对应的结果。以下代码片段使用 map 输出了元素对应的平方数:

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

Collectors.toMap 有三个重载方法:

toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper);
toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,
        BinaryOperator<U> mergeFunction);
toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,
        BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier);

参数解释:

(1)keyMapper:Key 的映射函数
(2)valueMapper:Value 的映射函数
(3)mergeFunction:当 Key 冲突时,调用的合并方法
(4)mapSupplier:Map 构造器,在需要返回特定的 Map 时使用

示例:
过去的做法(List 转 Map)

List<User> userList = new ArrayList<>();
userList.add(new User().setId("A").setName("张三"));
userList.add(new User().setId("B").setName("李四"));
userList.add(new User().setId("C").setName("王五"));
//遍历
Map<String, String> map = new HashMap<>();
for (User user : userList) {
    map.put(user.getId(), user.getName());
}

用 Collectors.toMap:

userList.stream().collect(Collectors.toMap(User::getId, User::getName));

转载自:1、java8 .stream().map().collect() 的用法
2、关于collect.stream().collect()方法的使用
3、Collectors.toMap 使用技巧 (List 转 Map超方便)

17、mybatis 映射内部类

参考文章:mybatis映射内部类的使用及注意事项

18、

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-30 00:38:26  更:2022-09-30 00:42:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/30 13:37:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码