1.抽象类为什么不能创建对象?
①把一些具有相同行为的方法和属性进行抽取,从而集成到一块,就定义成为一个抽象类。
②抽象类当中一定有抽象方法,这样就方便让子类去继承,因为不同的子类想要实现的功能可能不一样,所以才要去继承从而实现它当中的抽象方法,去扩展它的功能,从而实现需求。
③我们都知道,创建对象的目的就是为了通过对象去调用类中的属性和方法。如果抽象类自己去创建对象,由于它当中的抽象方法都只进行了声明而并未具体实现,所以这样的调用没有任何意义。所以就有抽象类不能创建对象,不能实例化这一要求。
2.MySql查询语句关键字的执行顺序
在MySql查询语句当中,关键字的执行顺序大致如下:
执行优先级 | 关键字 | 关键字的作用 |
1 | FROM | from子句返回初始结果集 |
2 | ON | 设置多表之间的连接条件。 |
3 | JOIN | 多表关联 |
4 | WHERE | 进行条件筛选 |
5 | GROUP BY | 按照关键字进行分组 |
6 | HAVING | 对分组结果进行筛选 |
7 | DISTINCT | 对结果集进行去重复 |
8 | ORDER BY | 对结果进行排序 |
9 | LIMIT | 返回表中指定行范围的数据 |
简单来记忆就是:from->where->group by->having->select->order by
3.Statement和PreparedStatement的区别
4.悲观锁,乐观锁,表级锁,行级锁
悲观锁
每次获取数据的时候担心数据被修改,所以每次获取数据的时候都会进行加锁确保自己使用过程中数据不会被别人修改,使用完成后对数据进行解锁。由于数据进行加锁,期间对改数据进行读写的其他线程都会进行等待。
悲观锁需要使用数据库的锁机制,比如数据库有表级排它锁,有行级排它锁。
假定一切操作都可能发现并发冲突,所以采取悲观态度。通过加锁,屏蔽一切可能违反数据完整性的操作
适用场景:比较适合写入操作比较频繁的场景。如果出现大型的读取操作,每次读取的时候都会进行加锁,这样会增加大量的锁的开销,降低系统的吞吐量。
乐观锁
乐观锁,简单地说,就是从应用系统层面上做并发控制,加锁。
实现乐观锁常见的方式:版本号version
实现方式:在数据表中增加版本号字段,每次对一条数据做更新之前,先查出该条数据的版本号,每次更新数据都会对版本号进行更新。在更新时,把之前查出的版本号跟库中数据的版本号进行比对,如果相同,则说明该条数据没有被修改过,执行更新。如果比对的结果是不一致的,则说明该条数据已经被其他人修改过了,则不更新,客户端进行相应的操作提醒。
乐观锁其实不是真实的去锁住记录不让访问,或者不让更新。假定操作很少发生冲突,一般对于读多写少的情况,只在提交操作时检查是否违反数据完整性。乐观锁不能解决脏读的问题。可以通过版本号是否比上个版本号或者时间戳来实现。
适用场景:比较适合读取操作比较频繁的场景,如果出现大量的写入操作,数据发生冲突的可能性就会增大,为了保证数据的一致性,应用层需要不断的重新获取数据,这样会增加大量的查询操作,降低系统的吞吐量。
表级锁,行级锁
在数据库中:表级锁,where用的是非主键;行级锁,where用主键一般是id;如果用表级锁,其他客户将不能进行查询操作,因此开发中一般用行级锁。
以mysql为例,有索引并且使用了该索引当条件的时候就是行级锁,没有索引的时候就是表级锁。innodb 的行级锁是在有索引的情况下,没有索引的表是锁定全表的。
行级锁,一般是指排它锁,即被锁定行不可进行修改,删除,只可以被其他会话select。行级锁之前需要先加表结构共享锁。
表级锁,一般是指表结构共享锁锁,是不可对该表执行DDL操作,但对DML操作都不限制。
行级锁之前需要先加表结构共享锁。
行级锁的缺点:开销大,加锁慢,会出现死锁
行级锁的优势:锁的粒度小,发生锁冲突的概率低,处理并发的能力强
行级锁访问数据库的时候针对整个行数据,自动加锁。对于UPDATE、 DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁;对于普通SELECT语句,InnoDB不会加任何锁。
表级锁访问数据库的时候针对整个表数据,自动加锁。查询操作(SELECT) ,会自动给涉及的所有表加读锁,更新操作(UPDATE、 DELETE、INSERT),会自动给涉及的表加写锁。
适用场景:表级锁使用与并发性不高,以查询为主,少量更新的应用,比如小型的web应用;
而行级锁适用于高并发环境下,对事务完整性要求较高的系统,如在线事务处理系统。