java常见面试题

1.sql优化常用方法

1.查询条件减少使用函数,避免全表扫描
2.减少不必要的表连接
3.有些数据操作的业务逻辑可以放到应用层进行实现
4.可以使用with as
5.使用“临时表”暂存中间结果
6.不要把SQL语句写得太复杂
7.不能循环执行查询
8.用 exists 代替 in 
9.表关联关系不要太纠结
10。查询多用索引列取查,用charindex或者like[0-9]来代替%%
11.inner关联的表可以先查出来,再去关联leftjoin的表
12.可以进行表关联数据拆分,即先查出核心数据,再通过核心数据查其他数据,这样会快得多
13.参考SQL执行顺序进行优化
14.表关联时取别名,也能提高效率
15.使用视图,给视图建立索引进行优化

2.mybatis中#和$的区别

1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id".
  
2. $将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id,  如果传入的值是id,则解析成的sql为order by id.
  
3. #方式能够很大程度防止sql注入。
  
4.$方式无法防止Sql注入。

5.$方式一般用于传入数据库对象,例如传入表名.
  
6.一般能用#的就别用$.

MyBatis排序时使用order by 动态参数时需要注意,用$而不是#

字符串替换
默认情况下,使用#{}格式的语法会导致MyBatis创建预处理语句属性并以它为背景设置安全的值(比如?)。这样做很安全,很迅速也是首选做法,有时你只是想直接在SQL语句中插入一个不改变的字符串。比如,像ORDER BY,你可以这样来使用:
ORDER BY ${columnName}
这里MyBatis不会修改或转义字符串。

重要:接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的SQL注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查

 

4.mysql和hibernate的区别

mybatis与hibernate一样是个orm数据库框架。它与hibernate区别是非常大的,有以下几点:

总结起来:

mybatis:小巧、方便、高效、简单、直接、半自动

hibernate:强大、方便、高效、复杂、绕弯子、全自动

1. hibernate是全自动,而mybatis是半自动。

hibernate完全可以自动生成sql。而mybatis仅有基本的字段映射,仍然需要通过手写sql来实现和管理。

2. hibernate数据库移植性远大于mybatis。

hibernate通过它强大的映射结构和hql语言,大大降低了对象与数据库(oracle、mysql等)的耦合性,而mybatis由于需要手写sql,移植性也会随之降低很多,成本很高。

3. hibernate拥有完整的日志系统,mybatis则欠缺一些。

hibernate日志系统非常健全,涉及广泛,而mybatis则除了基本记录功能外,功能薄弱很多。

4. mybatis相比hibernate需要关心很多细节

hibernate配置要比mybatis复杂的多,学习成本也比mybatis高。但也正因为mybatis使用简单,才导致它要比hibernate关心很多技术细节。mybatis由于不用考虑很多细节,开发模式上与传统jdbc区别很小,hibernate则正好与之相反。但是如果使用hibernate很熟练的话,实际上开发效率丝毫不差于甚至超越mybatis。

5. sql直接优化上,mybatis要比hibernate方便很多

由于mybatis的sql都是写在xml里,因此优化sql比hibernate方便很多。而hibernate的sql很多都是自动生成的,无法直接维护sql;总之写sql的灵活度上hibernate不及mybatis。

mybatis:

1. 入门简单,即学即用,提供了数据库查询的自动对象绑定功能。

2. 可以进行更为细致的SQL优化,可以减少查询字段。

3. 缺点就是框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。

4.二级缓存机制不佳。

hibernate:

1. 功能强大,数据库无关性好,O/R映射能力强。

2. 有更好的二级缓存机制,可以使用第三方缓存。

3. 缺点就是学习门槛不低,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡取得平衡,以及怎样用好Hibernate方面需要你的经验和能力都很强才行。

举个形象的比喻:

mybatis:机械工具,使用方便,拿来就用,但工作还是要自己来作

hibernate:智能机器人,但研发它(学习、熟练度)的成本很高,工作都可以摆脱他了,但仅限于它能做的事。

5.springmvc流程?视图的好处?

spring mvc工作机制?MVC里面视图的好处?

工作机制:客户端请求提交到DispatcherServlet

由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller

DispatcherServlet将请求提交到Controller

Controller调用业务逻辑处理后,返回ModelAndView

DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图

视图负责将结果显示到客户端

视图的好处:视图对象的定义比实体定义还要简单,不需要注解,不需要映射,但是唯一不同的是我们需要额外构造一个带有字段初始化的构造函数

7.事务

 

 

8.maven常用命令

1、mvn clean 
说明: 清理项目生产的临时文件,一般是模块下的target目录
2、mvn package 
说明: 项目打包工具,会在模块下的target目录生成jar或war等文件,如下运行结果。
3、mvn test 
说明: 测试命令,或执行src/test/java/下junit的测试用例.
4、mvn install 
说明: 模块安装命令 将打包的的jar/war文件复制到你的本地仓库中,供其他模块使用 -Dmaven.test.skip=true 跳过测试(同时会跳过test compile)
5、mvn deploy 
说明: 发布命令 将打包的文件发布到远程参考,提供其他人员进行下载依赖 ,一般是发布到公司的私服,这里我没配置私服,所以就不演示了

9.spring核心ioc和aop

10. spring核心:aop和ioc的解释?隔离范围? 3种注入方法?

(1)aop:Spring提供了对AOP技术的良好封装, AOP称为面向切面编程,就是系统中有很多各不相干的类的方法,在这些众多方法中要加入某种系统功能的代码;例如,加入日志,加入权限判断,加入异常处理,这种应用称为AOP。实现AOP功能采用的是代理技术,客户端程序不再调用目标,而调用代理类,代理类与目标类对外具有相同的方法声明,有两种方式可以实现相同的方法声明,一是实现相同的接口,二是作为目标的子类在,JDK中采用Proxy类产生动态代理的方式为某个接口生成实现类,spring提供了这种支持,只需要在spring配置文件中配置这两个元素即可实现代理和aop功能;

(2)Ioc:Spring提供了对IOC良好支持,IOC是一种编程思想,是一种架构艺术,利用这种思想可以很好地实现模块之间的解耦。IOC也称为DI(Depency Injection);IOC可以理解为‘面向接口编程思想’的一种实现方法,通过IOC实现了强制的‘面向接口编程’。

(3)隔离范围: Spring支持JDBC规范定义的四种隔离级别

Default默认的事务隔离级别

READ_UNCOMMITTED读未提交,一个事务可以操作另外一个未提交的事务,不能避免脏读,不可重复读,幻读,隔离级别最低,并发性 能最高

READ_COMMITTED读已提交,一个事务不可以操作另外一个未提交的事务, 能防止脏读,不能避免不可重复读,幻读。

repeatable_read能够避免脏读,不可重复读,不能避免幻读

SERIALIZABLE隔离级别最高,消耗资源最低,代价最高,能够防止脏读, 不可重复读,幻读。

(4)Spring的注入和IoC反转控制是一回事;关于getter和setter方式的注入;

Autowire=”defualt”;autowire=”byName”;autowire=”byType”;

10.ssm和ssh区别

(1)基于MVC三层架构,使用ssh框架 or ssm框架 or ssi框架,采用面向接口的方式编程。
共同点是struts、spring,不同点是nibernate和mybatis、ibatis。

(2)相对Hibernate“O/R”而言,iBATIS 是一种“Sql Mapping”的ORM实现。

(3)由于hibernate是完全面向对象的编程,在实现dao中就非常的方便,而且不重复;当mybatis在.java代码中也是可以做到不重复,麻烦一点的是,每个映射文件都必须编写几乎相同的配置,除了resultType不一样。

(4)hibernate在实际编程中可以把基础的CRUD封装,比如BaseDao类。其它类只要去继承BaseDao就能执行所有的基础的CRUD。这样就非常方便。这个带来的好处还有,可以建立BaseService和BaseAction。 

由于mybatis的映射文件中,虽然SQL语句中的表名可以通过parameterType指定,但是resultType必须定死,不能以参数 的形式给予指定。导致的结果就是所有的DAO类的每个CRUD都必须和指定的映射文件绑定在一起,以至于不可能存在BaseDao类。当然也就不能建立 BaseService和BaseAction。

11.hibernate三种状态

瞬时(transient):也叫自由状态.数据库中没有数据与之对应,超过作用域会被JVM垃圾回收器回收,一般是new出来且与session没有关联的对象。

持久(persistent):数据库中可能有数据与之对应(save),当前与session有关联,并且相关联的session没有关闭,事务没有提交;持久对象状态发生改变,在事务提交时会影响到数据库(hibernate能检测到)。

脱管(detached):也叫游离状态.数据库中可能有数据与之对应,但当前没有session与之关联,但是有oid;托管对象状态发生改变,hibernate不能检测到。

区别:Transient状态的实体缺乏与数据库表记录之间的联系,而Detached状态的实体恰恰相反.只不过是脱离了session这个数据库操作平台而已.

12.hibernate分页

1.HQL查询:Query query=session.createQuery(from 实体类);
2.从第几条开始:query.setFirstResult(mini);
3.每次最多提取多少条数据:query.setMaxResults(max);接收返回的结果集:List<实体类> HousesList=query.list();

13.四大作用域

四大作用域:page对象表示当前一个JSP页面,可以理解为一个对象本身,是代表与一个页面相关的对象和属性;一个页面由一个编译好的 Java servlet 类表示,

request是代表与 Web 客户机发出的一个请求相关的对象和属性。一个请求可能跨越多个页面,涉及多个 Web 组件(由于 forward 指令和 include 动作的关系);用户端请求

session是代表与用于某个 Web 客户机的一个用户体验相关的对象和属性。一个 Web 会话可以也经常会跨越多个客户机请求 与请求有关的会话期 

application是代表与整个 Web 应用程序相关的对象和属性。这实质上是跨越整个 Web 应用程序,包括多个页面、请求和会话的一个全局作用域 正在执行的内容

14.九大内置对象

(1)request 用户端请求,一次请求.此请求会包含来自GET/POST请求的参数

    response 网页传回用户端的回应

    pageContext 网页的属性是在这里管理

session 与请求有关的会话期 

application servlet 正在执行的内容

out 用来传送回应的输出 

config servlet的构架部件

page JSP网页本身 

exception 针对错误网页,未捕捉的例外

15. string、stringbuffer和stringbuilder的区别?哪个更安全?为什么?hashmap为什么查询的比较快?

(1)JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用StringBuffers来动态构造字符数据。另外,String实现了equals方法;而StringBuffer没有实现equals方法,所以,new StringBuffer(“abc”).equals(new StringBuffer(“abc”)的结果为false。

(2)StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改;通过某些方法调用可以改变该序列的长度和内容,可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致;

(3)StringBuilder一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。(如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。但将 StringBuilder 的实例用于多个线程是不安全的。如果需要这样的同步,则建议使用 StringBuffer。);

(4)HashMap是Hashtable的轻量级实现(非同步非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,在只有一个线程访问的情况下,效率要高于Hashtable。

16. sleep&wait区别和联系?

(1)这两个方法来自不同的类分别是,sleep来自Thread类,和wait来自Object类;sleep是Thread的静态类方法,谁调用的谁去睡觉,即使在a线程里调用了b的sleep方法,实际上还是a去睡觉,要让b线程睡觉要在b的代码中调用sleep。

(2)最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。sleep不出让系统资源;wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的 运行资源不够,再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,才会进入就绪队列等待OS分配系统资源。 sleep(milliseconds)可以用时间指定使它自动唤醒过来,如果时间不到只能调用interrupt()强行打断;

17.重写和重载的区别?

(1)重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同);

(2)重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现;只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常;子类方法的访问权限只能比父类的更大,不能更小。如果父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法;

18.手写单例模式(饿汉和饱汉模式)和工厂模式?

//(1)单例饿汉模式://饿汉式单例类.在类初始化时,已经自行实例化 
  public class Singleton1 {
      //私有的默认构造子
      private Singleton1() {}
      //已经自行实例化 
      private static final Singleton1 single = new Singleton1();
      //静态工厂方法 
      public static Singleton1 getInstance() {
          return single;
     }
 }

//(2)懒汉模式:懒汉式单例类.在第一次调用的时候实例化 
  public class Singleton2 {
      //私有的默认构造子
      private Singleton2() {}
      //注意,这里没有final    
      private static Singleton2 single=null;
      //静态工厂方法 
      public synchronized  static Singleton2 getInstance() {
           if (single == null) {  
              single = new Singleton2();
          }  
         return single;
     }
 }

//(3)工厂模式:

interface IFactory{

public IProduct createProduct();}

Class Factory implements IFactory{

public IProduct createProduct(){return new Product();}}

Public class client{

Public Static void main (String [] args){IFactory factory=new Factory();

IProduct product=factory.createProduct();

product.ProductMethod();}}

19.get和post的区别:

GET在浏览器回退时是无害的,而POST会再次提交请求。
 
GET产生的URL地址可以被Bookmark,而POST不可以。

GET请求会被浏览器主动cache,而POST不会,除非手动设置。

GET请求只能进行url编码,而POST支持多种编码方式。

GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。

GET请求在URL中传送的参数是有长度限制的,而POST么有。

对参数的数据类型,GET只接受ASCII字符,而POST没有限制。

GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息

GET参数通过URL传递,POST放在Request body中。

20.转发和重定向区别:

1、重定向两次请求,转发一次请求 
2、重定向地址栏的地址变化,转发地址不变 
3、重新定向可以访问外部网站 转发只能访问内部资源 
5、转发的性能要优于重定向 
注意:客户端地址与服务器端地址的写法? 
客户端地址: 
是客户端去访问服务器的地址,服务器外部的地址,特点:写上web应用名称 
服务器端地址: 
服务器内部资源的跳转的地址,特点:不需要写web应用的名称

21.session和cookie区别:

1、cookie数据存放在客户的浏览器上,session数据放在服务器上。

2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
   考虑到安全应当使用session。

3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
   考虑到减轻服务器性能方面,应当使用COOKIE。

4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

5、所以个人建议:
   将登陆信息等重要信息存放为SESSION
   其他信息如果需要保留,可以放在COOKIE中

22.where条件后的语句顺序影响查询效率吗?

绝对有影响,你可以参考下面两个sql语句来进行领悟:
select * from student where sex=1  and age>30
和
select * from student where age>30 and sex=1

23.scope的区间?

singleton单例,prototype多例,request,session

24.hashMap遍历方式?

public static void main(String[] args) {
  Map<String,String> map=new HashMap<String,String>();
        map.put("1", "value1");
        map.put("2", "value2");
        map.put("3", "value3");
        map.put("4", "value4");
        
        //第一种:普通使用,二次取值
        System.out.println("\n通过Map.keySet遍历key和value:");  
        for(String key:map.keySet())
        {
         System.out.println("Key: "+key+" Value: "+map.get(key));
        }
        
        //第二种
        System.out.println("\n通过Map.entrySet使用iterator遍历key和value: ");  
        Iterator map1it=map.entrySet().iterator();
        while(map1it.hasNext())
        {
         Map.Entry<String, String> entry=(Entry<String, String>) map1it.next();
         System.out.println("Key: "+entry.getKey()+" Value: "+entry.getValue());
        }
        
        //第三种:推荐,尤其是容量大时  
        System.out.println("\n通过Map.entrySet遍历key和value");  
        for(Map.Entry<String, String> entry: map.entrySet())
        {
         System.out.println("Key: "+ entry.getKey()+ " Value: "+entry.getValue());
        }
        
        //第四种  
        System.out.println("\n通过Map.values()遍历所有的value,但不能遍历key");  
        for(String v:map.values())
        {
         System.out.println("The value is "+v);
        }
 }

25.String s=new  String("123");创建了几个对象?

注意:栈,堆和常量池,对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。

      对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。


首先在string池内找,找到?不创建string对象,否则创建,   这样就一个string对象 
遇到new运算符号了,在内存上创建string对象,并将其返回给s,又一个对象 

所以总共是2个对象 

一个例子: 
public class Test 
{ 
public static void main(String [] args) 
{ 
String s1=new String("test");//创建2个对象,一个Class和一个堆里面 
String s2="test";//创建1个对象,s2指向pool里面的"test"对象 
String s3="test";//创建0个对象,指向s2指想pool里面的那个对象 
String s4=s2;//创建0个对象,指向s2,s3指想pool里面的那个对象 
String s5=new String("test");//创建1个对象在堆里面,注意,与s1没关系 

System.out.println(s2=="test");//true s2=="test"很明显true 
System.out.println(s2==s3);//true,因为指向的都是pool里面的那个"test" 
System.out.println(s2==s4);//true,同上,那么s3和s4...:) 
System.out.println(s1==s5);//false,很明显,false 
System.out.println(s1==s2);//false,指向的对象不一样,下面再说 
System.out.println(s1=="test");//false,难道s1!="tset"?下面再说 

System.out.println("---------------"); 

s1=s2; 
System.out.println(s1=="test");//true,下面说 
} 
} 
说明:1,System.out.println(s1==s2);很明显,s2指向的对象"test"是在pool里面,而s1指向的是堆里面的"test"对象(s1指向的内存区),所以返回false. 
2,System.out.println(s1=="test");s1指向的是堆里面的"test"对象(s1指向的内存区),而"test"是程序刚刚建立的(其实是共用pool里面的那个已经创建了的"test"对象,也就是我们s2="test"时候,在pool里面创建的),所以s1指向的堆里的"test"对象 
和"test"(pool里面)并不是一样个对象,所以返回false. 
3,当我们s1=s2;的时候,很明显,把s2的指给了s1,s1指向pool里面的"test",这个时候,s2也指向了pool里面的"test"对象了,当System.out.println(s1=="test");时候,java虚拟机创建"test"对象,注意,其实没创建,和前面讲的一样,公用s1="test"创建的"test"对象(pool里面的),所以,s1=="test"(pool里面的),同样,s1=s2=s3=s4! 

而为什么在网上都说String s=new String("test");创建了2个对象?那可能因为它就写这么一句代码,误让人默认的认为执行代码之前并不实例任何一个String对象过(也许很多人不会这么想,),跟着别人或者不经思考的就说2个,斟是说存放在栈内存中专门存放String对象引用的s变量是一个对象!实在不可原谅! 

是于我的理解是否正确,也并不重要了,必竟我也写出了我想法了,再说了,我只是3流大学,不,是N流学校的学生罢了,再说了,我又不是SUN公司的头头,连个职工都不粘边,靠! 
罗里罗嗦的说了一下,好了,大家应该明白我的意思了. 

26.1.

26.char和varchar的区别?哪个需要补空?

1.首先明确的是,char的长度是不可变的,而varchar的长度是可变的,

定义一个char[10]和varchar[10],如果存进去的是‘abcd’,那么char所占的长度依然为10,除了字符‘abcd’外,后面跟六个空格,而varchar就立马把长度变为4了,取数据的时候,char类型的要用trim()去掉多余的空格,而varchar是不需要的,

2.char的存取数度还是要比varchar要快得多,因为其长度固定,方便程序的存储与查找;但是char也为此付出的是空间的代价,因为其长度固定,所以难免会有多余的空格占位符占据空间,可谓是以空间换取时间效率,而varchar是以空间效率为首位的。

3。char的存储方式是,对英文字符(ASCII)占用1个字节,对一个汉字占用两个字节;而varchar的存储方式是,对每个英文字符占用2个字节,汉字也占用2个字节,两者的存储数据都非unicode的字符数据。

27.union和union all的区别?

答案:union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则排序

      union all:对两个结果集进行并集操作,包括重复行,不进行排序

28.tomcat部署的方式哪几种?

1 直接将web项目文件件拷贝到webapps目录中

  这是最常用的方式,Tomcat的Webapps目录是Tomcat默认的应用目录,当服务器启动时,会加载所有这个目录下的应用。如果你想要修改这个默认目录,可以在conf下的server.xml文件里修改Host标签里的appBase值。

  这个方法实际上和在IDE开发环境里部署项目是一样的。

  用此方法的访问路径为http://localhost:8080/webname

2 修改Server.xml文件

  在conf下的server.xml文件里找到Host标签,在里面添加如下代码:

1 <Context path="/jfinal_demo" docBase="F:\work\jfinal_demo\WebRoot"  reloadable ="true" debug="0" privileged="true">
2 </Context> 
  path:是访问时的根地址,表示访问的路径,可以自定义,如上述例子中,访问该应用程序地址如下:http://localhost:8080/jfinal_demo;

  docbase:表示应用程序的路径,docBase可以使用绝对路径,也可以使用相对路径,相对路径相对于webapps ;

  reloadable:表示可以在运行时在classes与lib文件夹下自动加载类包。这个属性在开发阶段通常都设为true,方便开发;在发布阶段应该设置为false,提高应用程序的访问速度 ;

  其他属性参见相关文档。

3 在conf\Catalina\localhost 目录下添加xml配置文件

  新建名为jfinal_demo.xml文件,文件内容配置如下:

1 <Context path="/jfinal_demo" docBase="F:\work\jfinal_demo\WebRoot"  reloadable ="true" debug="0" privileged="true">
2 </Context> 
  Catalina\localhost目录tomcat下载下来默认是没有的,首次启动会自动创建,也可以手动创建;

      配置中可以去掉path属性,因为访问项目时的根路径只取决于XML文件的名称,如上述例子中,访问该应用程序地址如下:http://localhost:8080/jfinal_demo ;

      推荐使用第三种方式,因为不需要修改tomcat默认配置,对Tomcat的侵入性最小,并且如果想取消部署,直接删除xml配置文件即可。

 

以上几种方法都经过本人测试,除此之外还有Tomcat热部署的方式,后续有机会再加上。

29,union和union all有什么不同?

UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION。UNION ALL只是简单的将两个结果合并后就返回。这样,如果返回的两个结果集中有重复的数据,那么返回的结果集就会包含重复的数据了。从效率上说,UNION ALL 要比UNION快很多,所以,如果可以确认合并的两个结果集中不包含重复的数据的话,那么就使用UNION ALL。

30.char、varchar2、varchar有什么区别?

Char的长度是固定的,而varchar2的长度是可以变化的,比如,存储字符串“abc”对于char(20),表示你存储的字符将占20个字节,包含17个空,而同样的varchar2(20)只占了3个字节,20只是最大值,当你存储的字符小于20时,按实际长度存储。

char的效率要被varchar2的效率高。

目前varchar是varchar2的同义词,工业标准的varchar类型可以存储空字符串,但是oracle不能这样做,尽管它保留以后这样做的权利。Oracle自己开发了一个数据类型varchar2,这个类型不是一个标准的varchar,他将在数据库中varchar列可以存储空字符串的特性改为存储null值,如果你想有向后兼容的能力,oracle建议使用varchar2而不是varchar

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酒书

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值