1 MySQL
1.1 char和varchar的区别
char:是定长字符串,最长255个字符,当插入数据少于指定长度时,剩余空间会用空格填充,速度快但浪费空间;<br /> varchar:变长字符串,最长不超过65535个字节,当插入数据少于指定长度时,剩余空间会留给别的数据使用,节省空间但速度慢
having中条件的定义和where中很相似,但是having中可以直接用聚合函数,但是where中不能,
1.2 日期类型
1、date:年月日
2、time:时分秒
3、datetime:年月日 时分秒
4、timestamp:时间戳(实际存储的是一个时间毫秒值),与datetime存储日期格式相同。
timestamp最大表示2038年,而datetime范围是1000~9999
timestamp在插入数、修改数据时,可以自动更新成系统当前时间
1.3 SQL语句注意事项
- as用于定义别名(仅在查询的结果中作为列的表头显示),也可以省略as,where子句中不能使用列别名;
- order by 排序的列asc升序,desc降序,
- sum()返回某列值之和,avg()返回某列的平均值, 多个聚合函数可以一起查询
1.4 连接查询
1、左外连接查询:显示左侧表中的所有记录,如果在右侧表中没有对应的记录,则显示为null
如:select xx from a left join b on (a.id=b.id)
2、右外连接查询,显示右侧表中的所有记录,如果在左侧表中没有对应的记录,则显示为null
如:select xx from a right join b on (a.id=b.id)1.5 常见面试题
1、数据库外键约束的几种方法及区别
- cascade级联模式 ,父表的操作,对应的子表关联的数据也跟着操作
- district :严格模式(默认的),父表不能删除或更新一个已经被子表数据引用的记录。
- set null:(置空模式)父表被操作之后,子表对应的外键字段被置空。
- no action 拒绝删除或者更新父表。
2、char(10)和VARCHAR(10)主要的区别是什么?
1、char的长度是不可变的,而varchar的长度是可变的,
2、定义一个char[10]和varchar[10],如果存进去的是‘abcd’,那么char所占的长度依然为10,除了字符‘abcd’外,后面跟六个空格,而varchar就立马把长度变为4了,取数据的时候,char类型的要用trim()去掉多余的空格,而varchar是不需要的,
3、char的存取速度还是要比varchar要快得多,因为其长度固定,方便程序的存储与查找;但是char也为此付出的是空间的代价,因为其长度固定,所以难免会有多余的空格占位符占据空间,可谓是以空间换取时间效率,而varchar是以空间效率为首位的。
4、char的存储方式是,对英文字符(ASCII)占用1个字节,对一个汉字占用两个字节;而varchar的存储方式是,对每个英文字符占用2个字节,汉字也占用2个字节,两者的存储数据都非unicode的字符数据。
1.6 数据库的隔离级别问题
多事务并发执行的问题
(1)更新丢失
两个事务都同时更新一行数据,一个事务对数据的更新把另一个事务对数据的更新覆盖了。这是因为系统没有执行任何的锁操作,因此并发并没有被隔离开来。
(2)脏读
一个事务读取到了另一事务未提交的数据操作结果。这是相当危险的,因为很可能所有的操作都被回滚。
(3)不可重复读
不可重复读(Non-repeatable Reads):一个事务对同一行数据重复读取两次,但是却得到了不同的结果。
包括以下情况:
虚读:事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读取该数据时得到与前一次不同的值。
幻读:事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据或者缺少了第一次查询中出现的数据。
这是因为在两次查询过程中有另外一个事务插入数据造成的。
事务隔离级别
为了避免上面出现的几种情况,在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同。
**读未提交(Read Uncommitted):只处理更新丢失。如果一个事务已经开始写数据,则不允许其他事务同时进行写操作,但允许其他事务读此行数据。可通过“排他写锁”实现。
**读提交(Read Committed):处理更新丢失、脏读。读取数据的事务允许其他事务继续访问改行数据,但是未提交的写事务将会禁止其他事务访问改行。可通过“瞬间共享读锁”和“排他写锁”实现。
**可重复读取(Repeatable Read):处理更新丢失、脏读和不可重复读取。读取数据的事务将会禁止写事务,但允许读事务,写事务则禁止任何其他事务。可通过“共享读锁”和“排他写锁”实现。
**序列化(Serializable):提供严格的事务隔离。要求失去序列化执行,事务只能一个接一个地执行,不能并发执行。仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。
隔离级别越高,越能保证数据的完整性和统一性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免脏读,而且具有较好的并发性能。尽管它会导致不可重复读、幻读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。
数据库控制并发的方式种:
1、悲观并发控制**:悲观控制是最为常见的一种控制方式,我们所熟知的锁就属于悲观并发控制,当事务需要对资源进行操作时需要先获得资源对应的锁,保证其他事务不会访问该资源后,在对资源进行各种操作;在悲观并发控制中,数据库程序对于数据被修改持悲观的态度,在数据处理的过程中都会被锁定,以此来解决竞争的问题;
2、乐观并发控制:**乐观并发控制又被称为乐观锁,但其实这里并不存在一把真正意义上的锁,乐观锁更多的是一种控制机制,类似于协议一样的东西,只要遵守便能达到并发控制的效果;
1.7 MySQL索引类型
从数据结构角度
- B+树索引(O(log(n))):详解
- hash索引
- 仅仅能满足“=”,“IN”和“<=>”查询,不能使用范围查询
- 其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引.
- 只有Memory存储引擎显示才支持hash索引
- fulltest索引(现在MyISAM和InnoDB引擎都支持)
- r-tree索引(用于对GIS数据类型穿件SPATIAL索引)
从物理存储角度
- 聚集索引
- 非聚集索引
从逻辑角度
- 主键索引:特殊的唯一索引,不允许为空
- 普通索引或者单列索引
- 多列索引或者复合索引:复合索引指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用复合索引时遵循最左前缀集合
- 唯一索引或者非唯一索引
- 空间索引:空间索引是对空间数据类型的字段建立的索引,MYSQL中的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING、POLYGON。
- MYSQL使用SPATIAL关键字进行扩展,使得能够用于创建正规索引类型的语法创建空间索引。创建空间索引的列,必须将其声明为NOT NULL,空间索引只能在存储引擎为MYISAM的表中创建
2 JDBC
2.1如何通过JDBC访问数据库
JDBC(Java数据库连接)即利用Java程序操作数据库的一门技术
JDBC提供了连接数据库、执行sql语句及获取结果数据的各种访问数据库的方法。并为各种不同的数据库提供统一的访问接口。通过JDBC访问数据库一般需要如下步骤:
1.注册数据库驱动
Class.forName(“com.mysql.jdbc.Driver”);
2.获取数据库连接
Connection conn = DriverManager.getConnection(
“jdbc:mysql://localhost:3306/jt_db”,”root”,”root”);
3.获取传输器对象(Statement或PreparedStatement)
Statement stat = conn.createStatement();
4.利用传输器发送sql到数据库执行, 返回执行结果
String sql = “select from account”;
ResultSet rs = stat.executeQuery(sql);
5.处理结果
while (rs.next()) {
int id = rs.getInt(“id”);
String name = rs.getString(“name”);
double money = rs.getDouble(“money”);
System.out.println(
id+” : “+name+” : “+money);
}
*6.释放资源(依次将ResultSet、Statement(或PreparedStatement)、Connection对象关闭)
rs.close();
stat.close();
conn.close();
问:为什么要这么做呢?(1)这些对象使用完后后面几乎不会再用到,如果不释放会占用服务器的内存空间,容易造成内存溢出。(2)其中的Connection连接数是有限的,如不及时释放,别的用户可能会获取不到连接,将无法访问数据库。
2.2 Statement对象和PreparedStatement对象的区别
1、Statement传输器对象用于执行不带参数(提前将sql语句和参数拼接)的简单sql语句。如果每次执行的sql语句不同(即使sql骨架相同),数据库都要编译该sql语句。例如:
Statement stat = conn.createStatement();
stat.executeQuery(“select * from user where username=’zhansan’ and password=123”);
2、PreparedStatement对象表示预编译的sql语句的对象,用于执行带参数的预编译sql语句:
PreparedStatement ps = conn.prepareStatement(“select * from user where username=? and password=?”);
ps.setString(“zhangsan”);
ps.setString(“123”);
ps.executeQuery();
3、虽然Statement对象和PreparedStatement对象可以完成相同的功能。但是相比之下,
PreparedStatement对象具有如下优点:**
(1)防止sql注入攻击
PreparedStatement对象在执行sql时,提前将sql语句的骨架(骨干)发送给数据库编译并确定下来,由于sql语句的骨架已经确定,所以后面再传入的就只能是参数的值,如果参数值中包含了影响sql语句的关键字或者特殊字符,也只会当作普通文本来处理。因此不会产生sql注入攻击问题。
(2)代码可读性好并且省去了拼接sql语句的麻烦。
(3)可以提高程序执行的效率。
不管使用哪一个传输器发送sql语句到数据库执行,都会先编译再执行,如果下次执行的sql语句和之前执行的完全相同,则会直接使用之前编译好的,将不会再次编译。
在同一种操作中(例如根据用户名和密码查询用户),PreparedStatement对象执行的sql骨架每次都是相同的,因此只需要编译一次。效率较高。
而Statement对象在执行sql时,每次都是将sql骨架和参数拼接好,只要参数不同,整条sql语句也就不同,因此每次都需要编译。
2.3 什么是数据库连接池
所谓的池就是程序中用来共享资源的容器,比如线程池,常量池。
而数据库连接池就是用来存放连接的容器,在开发JDBC程序时,可以将数据库连接存放在池子(其实就是一个容器,比如数组或者集合等)中,用于在整个程序中共享连接。
2.4 连接池的工作原理(即为什么要使用连接池?)
通过传统JDBC操作数据库,需要连接时就创建一个连接,用完后需要将连接关闭还给数据库。当并发访问的用户非常多时,这种频繁开关连接的操作将会十分的耗费资源,并且效率低下。
因此我们可以在程序中创建一个连接池,当程序启动时就初始化一批连接放在池中供整个程序共享。当需要连接时从连接池中获取一个连接进行使用,当用完连接后将连接还回连接池中。这样一来既可以减少连接开关的次数,也可以实现连接的复用,从而提高程序执行的效率。
传统JDBC访问数据库:
使用JDBC+数据库连接池访问数据库:
2.5 事务四大特性
事务就是指将一堆sql的执行绑在一起,要么都执行成功,要么都执行失败,都执行成功才算成功,否则会恢复到执行前的状态
原子性:事务中所有的操作都是不可再分割的原子单位,事务中的所有操作要么都执行成功,要么都执行失败
一致性:事务执行前后,数据库状态与其他业务规则保持一致
隔离性:在并发操作中,不同的事务应该隔离开,不同的并发事务互不干扰
持久性:一旦事务提交成功,事务中的所有数据操作都必须被持久化的保存到数据库
3 Servlet、JSP
3.1什么是Servlet?
HTML只能保存静态网页内容,而在实际开发中,往往需要给用户展示动态页面。Servlet就可以用来生成动态页面。
(所谓的动态页面是指:能够根据不同时间、不同用户而显示不同内容的页面,比如:留言板、订单页面、购物车页面等)
什么是Servlet呢?Servlet是SUN公司提供的动态Web资源开发技术,其本质上就是采用Java语言编写的服务器端程序。这段程序必须要放在Servlet容器中,由容器调用才可以执行。其主要作用是处理客户端的请求,并将处理结果响应给浏览器。例如:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write(“Hello…”+new Date().toString());
}
3.2 JSP和Servlet有哪些相同点和不同点?他们之间的联系是什么?
1.相同点: JSP和Servlet都可以用于接收客户端请求、处理请求,并做出响应。
2.不同点:
(1) Servlet更适合处理逻辑,不适合作数据展示(即响应页面)
(2) JSP更适合展示数据,不适合处理逻辑
(3) Servlet没有内置对象、JSP中有内置对象
(4) 在MVC设计模式中,Servlet属于控制器(Controller),JSP属于视图(View)
3.两者之间的联系:
JSP在一次被访问时,JSP引擎会对JSP进行编译,编译后就变成了Servlet,本质上就是一个Servlet。
3.3描述Servlet调用过程
(1)浏览器向服务器发送请求(例如地址为:http://localhost/day13/TestServlet)
(2)服务端通过请求解析出浏览器访问的是哪一台主机(例如:localhost)
(3)服务端通过请求解析出浏览器访问的是哪一个WEB应用(例如:/day13)
(4)再通过请求解析出浏览器访问的是哪一个资源(例如:/TestServlet)
(5)如果该Servlet是第一次被访问,服务器会加载Servlet类,并创建该类的实例.
(6)调用Servlet的init方法进行初始化操作(服务器调用init()).
(7)在处理请求之前,创建代表请求的request对象和代表响应的response对象,传递给service方法。
(8)调用Servlet的service方法处理请求。将需要响应的数据写入response对象中
(9)服务器取出response中保存的数据,按照Http协议的格式发送给浏览器,响应完毕!
3.4描述Servlet生命周期
Servlet在第一次被访问时创建Servlet实例,创建之后服务器会立即调用init方法进行初始化的操作,创建之后,Servlet实例会一直驻留在服务器的内存中,为后续的请求服务. 只要有请求来访问这个Servlet,服务器就会调用service方法来处理请求,直到服务器关闭,或者WEB应用被移出容器,随着WEB应用的销毁,Servlet实例也会跟着销毁,在销毁之前服务器会调用destroy方法进行善后的处理。
3.5转发和重定向的区别(即forward和redirect的区别)?
(1)转发是同一个WEB应用内部资源之间的跳转,而重定向既可以是同一个WEB应用内部资源的跳转,也可以是不同的WEB应用或者不同的虚拟主机中资源的跳转.
(2)转发是一次请求,而重定向是两次请求
(3)转发前后地址栏的地址不会发生变化,而重定向前后地址栏地址会发生变化.
(4)转发前后的request对象是同一个,而重定向前后的request对象不是同一个.
3.6描述四大域对象的特征
1、PageContext域
(1)生命周期:开始访问JSP页面时创建PageContext对象,访问JSP页面结束时销毁PageContext对象
(2)作用范围:在整个JSP页面中
(3)主要功能:在整个JSP页面中实现数据的共享。
2、request域
(1)生命周期:一次请求开始时创建request对象,一次请求结束时销毁request对象。
(2)作用范围:在整个请求链中
(3)主要功能:在整个请求链中实现数据的共享
3、session域
(1)生命周期:
创建: 当第一次调用request.getSession()方法时将会创建session对象.
销毁:session分为三种情况:
a)超时销毁: 如果超过30分钟不操作session,session将会超时销毁.
b)自杀: 当调用session.invalidate()方法时会立即销毁session
c)意外身亡: 当服务器非正常关闭时,session会销毁! 当服务器正常关闭时,session将会以文件的形式保存在tomcat服务器work目录下
(2)作用范围:在整个会话范围内
(3)主要功能:在整个会话范围内实现数据的共享
4、ServletContext域
(1)生命周期:服务器启动WEB应用被加载之后立即创建ServletContext对象,服务器关闭或WEB应用被移出容器,销毁ServletContext对象。
(2)作用范围:在整个WEB应用中
(3)主要功能:在整个WEB应用范围内实现数据的共享
3.7 JSP的九大隐式对象是哪九个?
page、requeset、response、application(ServletContext)、config(ServletConfig)、session(HttpSession)、exception、out、pageContext
4 Cookie、Session
4.1什么是会话?描述Cookie和Session的工作原理
1、什么是会话:将浏览器和服务器之间的多次请求和响应加在一起就可以看作浏览器和服务器之间的一次会话。
2、Cookie的工作原理:
客户端向服务器发送请求需要保存数据时,服务器端获取到需要保存的数据,并将数据通过Set-Cookie响应头发送给浏览器,浏览器会以Cookie的形式保存起来(浏览器的内存中或者临时目录下).
当客户端再次发送请求访问服务器,服务器可以通过Cookie请求头获取上次发送给浏览器的Cookie信息,通过这种方式可以保存会话中产生的数据.
3、Session的工作原理:
浏览器向服务器发送请求需要保存数据时,在服务器端获取到需要保存的数据,并获取到session对象,接着将数据保存在Session中,在响应时将session的ID以Cookie的形式发送给浏览器保存
当浏览器再去访问服务器时,请求中会携带着上次保存的sessionID,服务器可以通过sessionID获取到之前的session,再从session中获取到之前为当前浏览器保存的数据,通过这种方式,可以来保存会话中产生的数据!
4.2描述Cookie和Session的作用、区别和各自的应用范围
1.Cookie和Session的作用:
Cookie和Session都是会话技术,都可以用于保存会话过程中产生的数据,比如作为购物车用于保存商品信息.
2.Cookie和Session的区别:
(1)Cookie是将会话中产生的数据保存在客户端,是客户端的技术
(2)Session是将会话中产生的数据保存在服务器端,是服务器端的技术
(3)Cookie保存的信息的时间比较长,但是安全性不高,可能随着用户的操作,Cookie会被清空,所以Cookie存储数据的稳定性比较差。因此Cookie适合存放要保存时间较长,但安全性要求不高的信息
(4)Session通常保存信息的时间比较有限,但安全性比较高,因为是保存在服务器端,不会随着用户的操作而导致Session意外丢失,因此session适合存放安全性要求比较高,但是不需要长时间保存的数据。
(5)在性能上,Cookie性能更高一些。Cookie是将数据保存在用户各自的客户端浏览器中,而Session是服务器端的对象,是将数据(在一定时间内)保存在服务器端,因此当访问量增多时,会降低服务器的性能。
(6)在数据量上,单个Cookie保存的数据量不能超过4KB,而很多浏览器都限制一个站点给浏览器最多发送20个Cookie。而Session不存在此问题。
3.各自的应用范围:
Cookie:(1)实现购物车 (2)实现”记住用户名”功能 (3)实现7/30天自动登陆 等
Session:(1)实现购物车 (2)保存用户登录状态 等
5 HTTP协议、服务器
5.1描述HTTP协议的作用及具体内容(请求和响应的结构)
1、Http协议的作用:用来规定浏览器客户端和服务器之间通信的格式。即规定了浏览器在发送请求时该符合什么样的格式,和服务器在做响应时该符合什么样的格式。
2、HTTP协议的内容:HTTP请求(请求行、若干请求头、请求实体内容)、HTTP响应(状态行、若干响应头、响应实体内容)
5.2简述http请求报文的结构(HTTP请求信息的格式)
请求报文/请求信息中包含三部分内容, 分别为请求行、若干请求头、请求实体内容, 如下:
1.请求行:
GET /test/index.jsp HTTP/1.1
2.若干请求头:
host : localhost
xxx : xxx
…
(一个空行)
3.请求实体内容
如果请求方式为GET提交,请求实体中没有任何数据
如果请求方式为POST提交,并且请求中携带了数据,此时请求实体中才会有数据
5.3 GET请求方式和POST请求方式的区别(重点)
在HTTP协议中定义了7种请求方式,但是其中最常用的就是GET和POST。
GET和POST方式都可以向服务器发送请求,并且都可以在发送的请求中向服务器提交数据。
而两种方式的区别主要体现在请求参数传输过程的不相同。
1、GET提交方式
(1)通过地址栏URL提交数据, 相对不安全
采用GET提交向服务器向服务器发送数据时,需要将数据拼接在URL的后面进行发送,例如:(其中URL和数据之间用 “?” 连接,多个参数之间用 “&” 连接)
http://localhost/test/LoginServlet**?**username=zhangsan&password=123
由于这种方式会将数据显示在地址栏上,数据被彻底 “暴露” 出来,因此非常不安全。
(2)通过地址栏提交数据, 数据量不能太大。
由于浏览器对URL长度有限制,因此采用GET方式提交的数据量非常小。通常在1KB左右(有的浏览器限制为4KB)。
2、POST提交方式
(1)通过请求实体提交数据, 相对更安全。
(2)通过请求实体提交数据, 理论上没有数据量的限制。
区别总结:**
- GET在浏览器回退时是无害的,而POST会再次提交请求。
- GET请求会被浏览器主动cache,而POST不会,除非手动设置。
- GET请求只能进行url编码,而POST支持多种编码方式。
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
- GET请求在URL中传送的参数是有长度限制的,而POST么有。
- 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
- GET参数通过URL传递,POST放在Request body中。
- GET产生一个TCP数据包;POST产生两个TCP数据包(基于TCP)。
- 对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。