(1)视图:
视图是一张虚拟的表,本质上是对基表的一条select查询语句.
然后给这条查询语句进行命名,即为视图名称.
当基表数据发生改变时,视图数据也发生改变.
视图的作用:
1.简化复杂查询
2.限制数据访问
视图语法:
create or replace VIEW 视图名称 AS subQuery; sunQuery:对应到基表的一条查询语句
create or replace VIEW view_myemp_20 AS select * from myemp where depton = 20;
(2)索引:
索引是基于表中的某一列来进行创建,作用是为了提高查询效率
单例索引:
create unique index 索引名 on 表名(字段名);
符合索引:
基于多列来创建的索引
例如:基于表中某两列来创建的索引,进行order by 会使用到
create unique index idx_myemp_deptno_salary on myemp(deptno,salary);
select id,name,deptno,salary from myemp order by deptno ASC,salary DESC;
(3) 触发器
数据库中与表相关的一段PL/SQL语句,主要作用是监听表的DML操作,
当执行了insert/update/delete之后,会自动触发存储在触发器中的PL/SQL语句
create or replace trigger trigger_savenewemp
after insert
on myemp
declare
begin
dbms_output.put_line('成功插入员工');
end;
/
触发器的使用场景:
1.复杂的安全性检查
2.数据的确认
3.数据的审计
4.数据的备份和同步
(4)存储过程:
数据库系统中一组提前编译好的PL/SQL语句集,可以将复杂的SQL语句进行封装,
只需要编译一次,以后不需要重复编译.可以经过存储过程名反复调用,减少工作量
create or replace procedure sayHello
AS
begin
dbms_output_line('helloword');
end;
/
调用存储过程
begin
sayHello();
sayHello();
end;
/
(5)线程
进程: 一个正在运行的程序,拥有该程序运行的所有的资源,包括资源的分配和任务的调度
线程: 在进程中负责具体代码的执行,一个进程至少有一个线程
并发: 多个任务独立执行,一起执行
同步: 同一时刻只能有一个任务执行,当这个任务执行完成之后,才能执行下一个任务
异步: 一个线程中多个任务同时执行,互不影响
线程锁: 当多个任务访问资源时,为了保证数据的安全,
当一个线程访问资源时,其它线程不能访问,等上一个线程访问完成之后才能访问.
同步锁: synchronized 修饰方法
阻塞线程的方法:
1) Thread.sleep(3000);
2) synchronized(slock){
slock.wait(3000);
slock.notify();
slock.notifyAll();全部唤醒
}
创建线程的方法:
1)继承Thread,重写run()方法
有开辟线程的能力,资源共享方面不是很方便
2)实现runable接口,实现该接口的run()方法
没有开辟线程的能力,资源共享方面很方便
线程池:
帮助我们管理线程,我们只需要执行的任务交给线程池,
线程池会根据任务的大小,任务的时长,会将不同的任务交给线程池中的任务执行.
线程死锁:
多个线程因竞争资源而造成相互等待.
若无外力的作用,这些线程将无法向前推进
防止线程死锁:
1)加锁顺序
2)加锁时限
3)加锁检验
进程和线程的区别:
1)进程时资源分配和调度的一个独立单元,线程是CPU调度的基本单元
2)同一个进程中可以包含多个线程
3)进程结束后它拥有的线程都将销毁,而线程的结束不会影响同个进程中的其它线程的结束
4)线程共享整个进程的资源,一个进程至少包含一个线程.
(6) Mysql优化
1)in和not in 要慎用,否则会导致全表扫描, 改为 between...and...
2)尽量避免在where后面的子句中使用or, 改为 union all
3)尽量避免在where的子句中进行表达式操作
select id from zhou where num / 2 = 100;
改为: select id from zhou where num = 100 * 2
4)任何时候都不要使用select * from zhou,用具体的字段代替
5)如果使用到临时表,在存储过程的最后务必将临时表删除
(7) 泛型:
JDK1.5之后的新特性
作用:
1.在编译期间规定好我们要使用的类型,将运行时产生的异常提前到编译器,有利于我们处理异常
2.将类,接口,方法等数据类型参数化,更加灵活,代码复用性更高
3.泛型没有多态的特点
4.泛型不影响真实类型
泛型类:
class 类型<形参1,形参2.....>{ }
实参只能是引用数据类型,而不能是基本数据类型
泛型方法:
修饰符 <形参1,形参2...> 返回值 方法名(参数列表) { }
泛型接口:
interface 接口名<形参1,形参2.....> { }
(8)单例模式:
当全局对象只需要一个,保证全局对象的唯一性,达到资源共享
饿汉式:
一开始就创建这个对象,线程不安全
优点:多线程访问时效率快
缺点:在不使用实例时占用内存空间
public class Singleton{
private Singleton(){ }
private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}
}
懒汉式:
用实例的时候才创建
优点: 在不使用实例时不占用内存空间
缺点: 多线程时需要通过同步的手段达到实例的唯一性,效率低
public class Singleton{
private Singleton() { }
private static Singleton instance = null;
public static synchronsized Singleton getInstance(){
if(instance == null){
instance = new Singleton();
return instance;
}
}
(9) Shiro授权流程:
1.调用Subject用户主体接口,委托给Security Manager(安全管理器)
2.Security Manager委托给Authorizer(授权器)
3.Authorizer在授权之前会调用Realm(安全数据源,shiro和数据库/数据源之间的桥梁)
4.Authorizer会判断Realm的权限/角色是否和传入的匹配
如果匹配返回true,否则返回false表示授权失败
(10)Oracle和Mysql的区别:
1.Oracle是大型数据库,Mysql是小型数据库。
Oracle市场占有率达40%,Mysql 20%左右
Oracle价格非常高,Mysql是开源的
2. Oracle支持大并发大访问量
3. Oracle安装完成之后需要3G左右,Mysql只需要152M.
使用Oracle占用特别大的内存空间和其它机器性能
4.操作上的区别:
1)Mysql有create table if not exixt 方式创建表
Oracle不支持if not exist和drop table if exists 语句
2)Mysql使用自动增长类型,在创建表时只需要指定表的逐渐即可auto_increment
Oracle不能使用auto_increment.
Oracle的主键一般默认是4个字节,Mysql没有要求
3)Mysql可以使用双引号包起字符串
Oracle只能用单引号包起字符串
4)分页
Oracle: page:当前页码, pageSize:每页显示个数
select * from (select rownum rn,zhou.*from zhou)
where rn between (page-1)*pageSize + 1 and page*pageSize
Oracle分页注意事项:
在使用rownum时,不能对rownum进行大于0的某一数的判断,
因为rownum必须从0开始递增
Mysql分页:
select * from 表明 limit 起始行号,行数。
起始的行号从0开始,如果和order by 连用。order by 在前
---列出总成绩并且按照降序排列,只打印三行
select name,sum(score) from score group by name order by sum(score) desc limit 3;
5)字符串的模糊查询
Mysql:
select * from 表名 where 字段名 like ‘%条件%’
Oracle: 不能使用索引,速度不快
---查询名字中第二个字母是a的员工的信息
select id,name from zhou where name like '_a%';
(11)关系型数据库和非关系型数据库的区别:
关系型数据库:表和表,表和字段,数据和数据库之间存在着关系
优点:关系型数据库有事物存在,保证数据的完整性和一致性
缺点: 因为数据和数据之间有关系,底层是运行了大量的运算,会降低性能
对海量数据的增删改查无能为力,海量数据的维护变得无力
(12)Servlet执行流程
Servlet作用:
处理服务器端的资源分配,前端发送过来的请求,并不是直接给服务器,
而是Servlet来处理请问,根据请求数据找到对应的资源,然后返回给前端。
Servlet执行流程:
1)浏览器输入访问路径
2)根据访问路径找到已注册的servlet名称。
3)根据映射找到对应的servlet名
4)根据servlet名找到我们全限定类名,即我们自己写的类
5)调用init()方法进行初始化
6)调用service()方法处理前端发送过来的请求
前端发送一次请求该方法被执行一次,所以该方法可以被多次执行
request:接受前端发送过来的参数,response:负责响应给前端数据
例如:登录操作
6.1)处理前端传递过来的数据:req.getParameter(" ")
6.2)生成一个json对象:JSONObject jObject = new JSONObject();
进行非空判断,调用dao层查询数据库
6.3)session存值,在jsp页面显示它
HttpSession session = req.getSession();
session.setAttribute("manager", manager);
6.4) 创建servlets层继承自HttpServlet,重写doGet(),doPost()方法
在doGet()方法里面写:
//将数据交给service层来处理
MyService service = new MyService();
String json = service.login(req,resp);
//给前端返回数据
req.setAttribute("json", json);
req.getRequestDispatcher("/login.jsp").forward(req, resp);
6.5)Login.jsp
String json = (String)request.getAttribute("json");
if(json != null){
JSONObject jsonObject = JSONObject.fromObject(json);
int code = jsonObject.getInt("code");
if(code == 0){
//登陆成功
response.sendRedirect(application.getContextPath() + "/index.jsp");
return;
} else{
out.print(jsonObject.get("msg"));
}
}
<script type="text/javascript">
$(document).ready(function(){
//获取到cookie的name和密码
var name = $.cookie("name");
var pwd = $.cookie("pwd");
console.log(name);
//把用户名和密码放到前端的input上 获取前端的框
$("#name").attr("value",name);
$("#PASSWORD").attr("value",pwd);
});
</script>
7)调用destory()方法终止(结束)
当servlet对象被释放时,会调用此方法,一般该方法会做一些扫尾工作
(例如:关闭数据库,将一些重要的数据保存起来)
Servlet是由JVM的垃圾回收器进行垃圾回收的
(13)九大内置对象:
request:请求对象;
response:响应对象
out: JSPWriter类实例,负责向前端输出数据
session: HttpSession类实例,追踪不同客户端的会话
application: ServletContext类的实例,可以作用于整个web项目的对象。
获取转发对象:getRequestDispatcher("");
获取当前根目录:getContextPath();
根目录:当前项目所需要的资源都在一个目录下,该目录为根目录
pageContext: 可以获得JSP页面所有对象,可以存值并指定有效范围
存储的数据默认只能在当前的⻚页⾯面使⽤用: setAttribute(“key1”, “value1”)
存储的数据在⼀一次会话中使⽤用: setAttribute(“key2”, “value2”, PageContext.SESSION_SCOPE)
page:当前JSP文件对象,类似java中this关键字
config: 获取xml中的配置内容,
相当于appliacation: config.getServletConfig()
exception:处理异常
获取异常信息:
exception.getMessage();
获取所有发⽣生异常的位置:
StackTraceElement[] elements = exception.getStackTrace();
打印发⽣生异常的地⽅方信息:
exception.printStackTrace();
(14)重定向和转发的区别
转发:
request.getRequestDispatcher(“new.jsp”).forward(request, response);
重定向:
response.sendRedirect( request.getContextPath( ) + "new.jsp")
1)重定向:浏览器的行为,发起了两次请求,两次响应
转发:服务器的行为,发起了一次请求,一次响应
2)重定向可以访问自己web应用以外的资源,转发只能转发给本项目其它资源
3)重定向地址栏会显示第二次请求的地址,传输的信息会丢失。
4)重定向需要给出全路径,即路径要包含项目名
转发只需给出转发的资源路径即可
5)重定向底下的代码还会执⾏行行, resp.sendRedirect之后,应紧跟⼀一句句return
Manager manager = (Manager)session.getAttribute("manager");
if(manager == null){
System.out.println("未登录");
response.sendRedirect(application.getContextPath()+"/managerLogin.jsp");
}
(15)MyBatis中#和$的区别:
1.#和$都能充当占位符,
#的底层是通过PreparedStatement实现的
$的底层是通过Statement实现的
2.只有在传入数据库对象时,才会用到$
2.1按照某个表进行查询时,传入表名;
2.2按照某一列进行排序时,传入类名
3.传入非数据库对象时最好用#不用$
4.#是先编译sql语句,在传值给传入的值都加上双引号
$是直接拼接字符串,不会给传入的值加上双引号
5.#会防止sql注入,$不会
(16)防止sql注入的问题:
sql注入:
查询时通过修改where后面的条件,将条件该为真,查询全表
防止sql注入:
预执行sql语句,提前判断该sql语句的语义和语法是否正确
当我们要查询的信息比较敏感,对安全性要求高,我们就使用prepareStatement,来进行查询