目录
5、MyBatis的${}和#{}的区别?什么情况下使用${}
两者的区别主要在于数据的存储形式不同。像Mysql、Oracle等都是关系型数据库,而Redis、MongoDB都是非关系型数据库。
关系型数据库的最大特征就是表,对象的属性映射为表的列名,数据按行填充,对数据进行CRUD的时候,都是基于表中的每一行数据进行操作的。
非关系型数据库的存储方式则是键值对,通过key:value的形式来保存对应的数据。
Byte、short、char、int、float、long、double、boolean
继承:从已有类中得到继承信息并创建新类的过程,可以使用现有类的所有功能,并且可以在无需重新编写原来类的情况下实现功能的扩展。
封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象进行操作,对不可信的类进行信息隐藏。
多态:对于同一个行为,不同的子类对象具有不同的表现形式。一个类实例(对象)的相同方法在不同情形有不同表现形式分为编译时多态(重载)和运行时多态(重写)。
EnableAutoConfiguration:让 Spring Boot 根据应用所声明的依赖来对 Spring 框架进行自动配置,一般加在主类上。
RestController:用于标注控制层组件(如struts中的action),包含@Controller和@ResponseBody
ResponseBody:表示该方法的返回结果直接写入HTTP response body中
Configuration:指出该类是 Bean 配置的信息源,相当于XML中的
ComponentScan:组件扫描。相当于
AutoWired:byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。当加上(required=false)时,就算找不到bean也不报错。
RequestMapping:用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
Qualifier:当有多个同一类型的Bean时,可以用@Qualifier("name")来指定。与@Autowired配合使用
#{}是预处理,${}是字符串替换。
Mybatis在处理${}时,会把${}的值替换为变量的值。而Mybatis在处理#{}时,会对SQL语句进行预处理,将#{}的值替换为?,并调用PreparedStatement的set方法进行赋值。
使用#{}可以防止SQL注入,提高系统的安全性。尽管$不安全,但是它可以解决一些特殊情况下的问题。如:表名作参数时用 ${}。如:select * from ${tableName}、order by 时用 ${}。如:select * from t_user order by ${columnName}。
(1)继承Thread类,重写run方法
- class MyThread extends Thread{
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + "正在执行");
- }
- }
-
- public class Day {
- public static void main(String[] args) {
- MyThread mt = new MyThread();
- mt.start();
- System.out.println(Thread.currentThread().getName() + "正在执行");
- }
- }
执行结果:
(2)实现Runnable接口,重写run方法
- class MyThread implements Runnable{
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + "正在执行");
- }
- }
-
- public class Day {
- public static void main(String[] args) {
- MyThread mt = new MyThread();
- Thread thread = new Thread(mt);
- thread.start();
- System.out.println(Thread.currentThread().getName() + "正在执行");
- }
- }
执行结果:
(3)实现Callable接口,重写call方法
- class MyThread implements Callable
{ - @Override
- public String call() {
- System.out.println(Thread.currentThread().getName() + "正在执行");
- return "success";
- }
- }
-
- public class Day {
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- Callable
callable = new MyThread(); - FutureTask
futureTask = new FutureTask<>(callable); - Thread thread = new Thread(futureTask);
- thread.start();
- System.out.println("Callable接口的返回值" + futureTask.get());
- System.out.println(Thread.currentThread().getName() + "正在执行");
- }
- }
执行结果:
(4)使用线程池
- public class Day {
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- ExecutorService threadPool = Executors.newCachedThreadPool();
- try {
- for (int i = 0; i < 5; i++) {
- threadPool.execute(()->{
- System.out.println(Thread.currentThread().getName() + "正在执行");
- });
- }
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- threadPool.shutdown();
- }
- }
- }
执行结果:
Java保证线程安全的方式有很多,其中较为常用的有三种,按照资源占用情况由轻到重排列,这三种保证线程安全的方式分别是原子类、volatile、锁。
原子类(JUC):JDK从1.5开始提供了java.util.concurrent.atomic包,这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。在atomic包里一共提供了17个类,按功能可以归纳为4种类型的原子更新方式,分别是原子更新基本类型、原子更新引用类型、原子更新属性、原子更新数组。无论原子更新哪种类型,都要遵循“比较和替换”规则,即比较要更新的值是否等于期望值,如果是则更新,如果不是则失败。
volatile:是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”以及防止指令重排序,从而可以保证单个变量读写时的线程安全。可见性问题是由处理器核心的缓存导致的,每个核心均有各自的缓存,而这些缓存均要与内存进行同步。volatile具有如下的内存语义:当写一个volatile变量时,该线程本地内存中的共享变量的值会被立刻刷新到主内存;当读一个volatile变量时,该线程本地内存会被置为无效,迫使线程直接从主内存中读取共享变量。
锁:原子类和volatile只能保证单个共享变量的线程安全,锁则可以保证临界区内的多个共享变量的线程安全,Java中加锁的方式有两种,分别是synchronized关键字和Lock接口。synchronized是比较早期的API,在设计之初没有考虑到超时机制、非阻塞形式,以及多个条件变量。若想通过升级的方式让它支持这些相对复杂的功能,则需要大改它的语法结构,不利于兼容旧代码。因此,JDK的开发团队在1.5新增了Lock接口,并通过Lock支持了上述的功能,即:支持响应中断、支持超时机制、支持以非阻塞的方式获取锁、支持多个条件变量(阻塞队列)。
除了以上三种方式外以外,juc包下还提供了一些线程同步工具类,如CountDownLatch(允许一个或多个线程等待其他线程完成操作)、Semaphore(信号量,可以控制同时访问特定资源的线程数量)等等.
我们也可以考虑使用ThreadLocal存储变量,ThreadLocal可以很方便地为每一个线程单独存一份数据,也就是将需要并发访问的资源复制成多份。这样一来,就可以避免多线程访问共享变量了,它们访问的是自己独占的资源,它从根本上隔离了多个线程之间的数据共享。
索引时对数据库表的一列或者多列的值进行排序的一种结构,使用索引可以快速访问数据表中的特定信息,常见的索引有以下几种:
普通索引:是基本的索引类型,可以为Null,可以有多个
主键索引:数据列不能重复,不能为Null,一个表上只有一个主键索引
组合索引:由多个列值组成的索引,既可以创建普通索引,也可以创建唯一索引。
唯一索引:数据列不允许重复,可以为Null,索引列的值必须是唯一的
全文索引:对文本的内容进行索引,在数据量大时取代like+%。
空间索引:对空间数据累心的字段建立索引,该列不能为空
条件中有or,例如select * from table_name where a = 1 or b = 3
在索引上进行计算会导致索引失效,例如select * from table_name where a + 1 = 2
在索引的类型上进行数据类型的隐形转换,会导致索引失效,例如字符串一定要加引号,假设 select * from table_name where a = '1'会使用到索引,如果写成select * from table_name where a = 1则会导致索引失效。
在索引中使用函数会导致索引失效,例如select * from table_name where abs(a) = 1
在使用like查询时以%开头会导致索引失效
索引上使用!、=、<>进行判断时会导致索引失效,例如select * from table_name where a != 1
索引字段上使用 is null/is not null判断时会导致索引失效,例如select * from table_name where a is null
mysql估计使用全表扫描要比使用索引快,则不使用索引。
对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度
对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少,不利于使用索引。
当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能
B+ 树是是一个n叉树,每个节点通常有多个孩子,一颗B+树包含根节点、内部节点和叶子节点。B+ 树通常用于数据库和操作系统的文件系统中。 在B+树中,所有的记录节点都是按照键值大小的顺序存放在叶子节点上。