回 到 目 录

 

 

六花酱赛高

JAVASE复习

JAVASE复习

 

 

目录:

  内部类

  枚举类

  垃圾回收

  修饰符

  与运行环境交互

  集合

     常用jvm启动参数     

  泛型

  异常

  mysql与sql

  JDBC编程

  注解

  

  多线程

  网络编程

  类加载和反射

 

 

 

 

 

内部类

1. 外部类可以通过非静态内部类对象访问内部类的private属性,内部类可以直接访问外部类的private属性,说明外部类和内部类都是在“一个类中”,这样才能相互访问到对方的private属性

 

2. 非静态内部类的实例化:new Outer().new Inner();//这个很好理解,Inner需要用outer对象来实例化,Inner的命名空间是Outer

 

3. 静态内部类的实例化: new Outer.Inner();

 

4. 内部类的子类的构造器调用父类构造器,要加上外部类做为命名空间:

SubInner.java code

 1 class Outer1 {
 2     class Inner {//注意权限限定,别private了,不然没法继承。如果是protected和默认权限,也要注意SubInner放在哪
 3         private String name;
 4         public Inner(String name) {
 5             this.name = name;
 6         }
 7     }
 8 }
 9 
10 public class SubInner extends Outer1.Inner {
11     public SubInner(Outer1 out, String name) {
12         out.super(name);
13 //super(name);//是错的,说明内部类是有命名空间的
14         //Outer1.super(name);//是错的,说明非静态内部类必须要存在于一个父类的实例中
15     }
16 }

 

 

5. 内部类生成的class文件:Outer$Inner.class

 

6. 局部内部类(在方法中定义的内部类)生成的class文件:OuterClass$NInner.class,局部内部类可能重名,所以N1开始递增

 

7. 个人觉得java使用内部类实现闭包和回调华而不实

 

枚举类:

1. switch语句可以用枚举类来做判断

 

2. Enum可以implements interface但是不能 extends class。原因是enum自动继承java.lang.Enum,不能再继承其他的类了!

 

3. 枚举类的对象在定义时可用类似与匿名内部类的方式来重写方法、添加方法、添加属性等

 

4. 枚举类默认是public final的。但可以使用匿名内部类的方式来给枚举类对象初始化,是因为写匿名内部类的时候jvm自动把枚举类弄成abstract而不使用final,但这个abstract不能让你显式的写上去,而且在其他地方不能让你继承枚举类,就算是匿名内部类也不行,如:

Season.java code

 1 //class A extends Season {//错的,除了给枚举对象初始化时可以继承,其他地方都不能继承
 2 //    
 3 //}
 4 public enum Season {//extends 是被不允许的,因为java没有多继承
 5     SPRING() {//使用匿名内部类给枚举对象初始化
 6         int a;
 7 
 8         @Override
 9         void func() {
10             
11         }
12     };
13     abstract void func();//在enum中可以写抽象方法
14     public static void main(String[] args) {
15         //Season s = new Season() {};错,即使是匿名内部类继承,也不能使用
16     }
17 }

 

 

垃圾回收:

  1. 对象的三个状态:可达、可恢复、不可达
  2. System.gc() = Runtime.getRuntime().gc()

   System.runFinalization() = Runtime.getRuntime().runFinalization()

  3. System.gc()之后Thread.sleep(int time), 几秒之后效果更好

  4. System.gc()之后System.runFinalization()类似于第三点,如:

Main.java code

 1 public class Main {
 2     public static void main(String[] args) throws Exception {
 3         for (int i = 0; i < 1000; ++i) {
 4             new Main();
 5         }
 6         System.gc();
 7         //Thread.sleep(10);
 8         System.runFinalization();
 9         System.out.println("如果\"清理\"出现在下面,说明没有及时清理");
10         // System.out.println(Runtime.getRuntime().freeMemory());
11     }
12 
13     @Override
14     public void finalize() {
15         System.out.println("清理");
16     }
17 }

 

 

  5. Gc只是建议jvm收集垃圾! runFinalization只是建议jvm调用可恢复对象的finalize方法

  6. 要想让gc更有效率,就得深入学习java垃圾回收机制以及优化,别再想强行释放的问题了

  7. 程序结束时可能先关闭标准输出流,再调用垃圾对象的finalize方法,所以你不一定能在小程序中看到 finalize方法的输出。又或者调用finalize方法的途中关闭标准输出流,所以肯能只输出到一句,第 二句就不输出了

 

  8. 讲到gc,就得知道java1.2开始的4中引用:强引用、软引用、弱引用、虚引用

      a) 平常用的就是强引用,强引用全部赋值为null时会回收,不一定会马上回收

      b) 软引用SoftReference,在虚拟机内存不足的时候会释放,使用前先把强引用关

        联软引用,然后把强引用赋值为null

      c) 弱引用WeakReference,不管怎样,都回收,不一定立即回收。使用方法同上

      d) 虚引用PhantomReference,无法从虚引用获得对象,与引用队列ReferenceQueue

        联用,用来查看对象是否以被回收,如果被回收,那么引用队列中存在那个虚引用

 

修饰符:

strictfp: 用来修饰浮点数,将严格按照IEEE-754来计算,使得计算更精确

native: 本地方法,一般用C语言来写,用来调用一些跟平台有关的函数或链接库,定义之后

    说明你的程序不再具有平台无关性。

    使用方法:

    1. native的方法声明,别写方法体

    2. 用javah编译第一部生成的class文件,将产生一个.h文件(C语言中叫头文 件)。

             3. 写一个.cpp文件实现native方法,其中需要包含第一部产生的.h头文件(.h 文件中又包含了JDK自带的jni.h文件).

             4. 将第二部中的.cpp文件变异成动态链接库文件。

             5. 在Java中调用System.loadLibrary()方法或RuntimeloafLibrary()方法加载 第三部产生的动态链接库文件,

      就可以在Java中调用这个native()方法了。

transient: Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,

      我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,

      可以在这个域前加上关键字transient。当一个对象被序列化的时候,

      transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。

volatile: 它是被设计用来修饰被不同线程访问和修改的变量,当变量被修改时,jvm会通知其他线程该变量已修改

 

 

与运行环境交互

  1. Scanner实例化时可指定输入流,也可以指定文件,不只有标准输入System.in~

Scanner一行一行地读取文件内容也是很方便的哦~

  2. System代表当前java程序的运行平台,不能实例化。提供标准输入、输出、错误,

可以得到环境变量等系统参数

  3. Runtime代表当前java的运行时环境,不能实例化,只能通过Runtime.getRuntime()

获取实例,可以得到处理器数量、空闲内存数等参数。可以另外启动一个进程来运行操作

系统的命令

  4. 工具类一般以s结尾,如ArraysCollectionsjava7新增的Objects

  5. BigDicemal实例化时要用字符串作为构造器参数,否则浮点数后面几位的随机数会导致精度

不好

 

集合

 1. 集合:两个接口: Collection和Map, collection下有三个接口:List、Queue、Set

 2. 集合只能保存对象,list.add(5);正确是由于自动装箱

 3. Iterator本身并不提供盛装对象的能力,有iterator对象必有一个Collection对象

 4. 在使用iterator遍历集合的时候,想要删除元素只能通过it.remove()删除当前

  元素,不能通过collection.remove(Object);来删除元素,否则极有可能可能会报

  java.util.ConcurrentModificationException异常

 5. foreach同上

 6. HashSet插入时调用hashCode和equals来比较两个对象,hashCode一样且

  equals为true,那就不插入。如果equals为false,hashCode不一样,

  那就插在不同位置上(hashCode决定位置)。如果equals为false且hashCode

  相等,那就插在同一个位置上的链表上(hash冲突)

 7. 不同类型的Field取得hashCode值的方式:

  boolean: hashCode=(f ? 0 : 1);

  整数类型:hashCode=(int)f;

  long:   hashCode=(int)(f ^ (f >>> 32));

  float:   hashCode=Float.floatToIntBits();

  double: long l = Double.doubleToLongBits(); hashCode=(int)(f ^ (f >>> 32));

  引用类型: hashCode=字段.hashCode();

 8. LinkedHashSet输出元素的顺序与插入元素的顺序一致。可能仅仅通过hashCode计算相对位置,

  比如说只插入a和b元素,a的hashCode是5,b的hashCode是8,那么a的next直接指向b,如果

  要插入c(hashCode=7),那么会插入在a和b之间。总之不会像数组哈希表一样空出下标为6和7的

  位置

 9. TreeSet使用红黑树作为数据结构,因此是有序的,效率比HashSet差一些。插入元素时,除第一个

  被插入的元素外,其他都要实现Comparable接口(当然最好也要给第一个实现);如果指定了比较

  器Comparator,可以不实现Comparable接口。

 10. 固定长度的List:工具类Arrays的内部类ArrayList是固定的,它和java.util.ArrayList是不同的,

  使用Arrays.asList(Object... a);返回的就是这个内部类,只能遍历,不能增加、删除元素

 11. java实现了优先队列PriorityQueue

 12. 双端队列接口: Deque,LinkedList实现了Deque,因此可以作为双端队列。ArrayDeque是数组

  形式的双端队列

 13.  Hashtable不允许使用null作为key或value,HashMap可以使用一个null来作为key,n个null

  作为value。装进它们的对象要重写hashCode和equals

 14. LinkedHashMap 与 8. 类似

 15. Properties可以读取XML配置(loadXml()),也可以写XML配置(storeToXml())

 16. WeakHashMap:装弱引用的hashmap。一般用来装一些不是要一直存在内存中的对象

 17. IdentityHashMap: 用==来比较

 18. HashSet和HashMap可以设置初始化容量以及负载极限。高负载极限换空间,低负载极限换时间

 19. 工具类Collections可以对集合排序、反转等操作,还能将非线程安全的集合类变成线程安全的

  集合类:synchronizedXxx();

  如:  Collections.synchronizedCollection(new ArrayList);

      Collections.synchronizedSet(new HashSet());

      Collections.synchronizedMap(new HashMap());

 

 

启动jvm的常用参数

  -Xms128m: 设置jvm堆内存初始大小为128M

  -Xmx512m:  设置jvm最大对内存大小为512M

  -verbose:gc  打印gc情况

 

 泛型

 1. java7的菱形语法: List<String> list = new ArrayList<>();

 2. 泛型的继承:

class A<T> {
    public T get(T t) {
        //T t = new T();T不能实例化
        return t;
    }
}

class B extends A {//继承A<String>或A都可以,但不能是A<T>,要想继承A<T>得写 class B<T> extends A<T>
    //get方法:如果继承A就不能加Override注释(raw type),继承了A<String>可以加注释
    public String get(String s) {
        return s;
    }
}

2. 泛型参数T只存在于编译期,在运行期期的时候将T给擦除并替换成xxx 

3. A<String>和A<Integer>是同一个类,因此getClass相等, 它们俩被当成同一个A类。

4. class A<T>, 由于同一个类共用一段栈内存来存放类成员,因此静态属性、静态方法、静态代码段都不能有泛型参数T,可以有其他泛型参数如<? extends Object>

5. 另外A<xxx>类是不存在的,因此不能用instanceof A<xxx>可以用instanceof A

6. A<Integer>并不是A<Number>的子类,要想同时使用Number和Integer可以把A写成:class A< ? extends Number>

7. class B extends A,那么可以写A[] a = new B[10];(A[]是B[]的父类,反过来赋值不行), 但是泛型不能这么写:A<Integer>[] a = new B<Interger>[10];

 

8. List<?> list = new ArrayList<String>();是对的,但是list.add(new Object());会报错,因为List<E>类的add方法是:boolean add(E e)。声明为List<?>将会导致add的方法的参数不知道是什么类型的,所以报错。然后add(null);是对的,因为null可以是所有引用类型的实例

9. 泛型参数可设定多个上限,如 class A<T extends Number & java.io.Serializable>,如果有类上限,那么类上限必须在第一位。用&隔开多个上限

10. java7的菱形语法与泛型构造器:

 1 public class A {
 2     public <T> A(T t) {
 3         
 4     }
 5     public static void main(String[] args) {
 6         new A("123");//与下面一句效果一样
 7         new <String> A("123");
 8         new A(1);//与下面一句效果一样
 9         A a = new <Integer> A(123);
10     }
11 }

11. javac增加命令-Xlint:unchecked可以忽略unchecked异常,系统会把class A<T>的T当成Object来处理

12. 可以指定多个泛型参数,如:class<T, S, R>

 异常

 1. Throwable是异常父类,其下两个子类,Error、Exception。Error会导致程序中断,没法处理,所以别catch

 2. 异常分为cheked异常和runtime异常,cheked异常是java

 3. java7可以catch多个异常,如: catch(IndexOfBoundsException|NumberFormatException|ArithmeticException e)

 4. 资源是没法自动回收的。资源一般有数据库连接、网络连接、磁盘文件等。因为try和catch不一定会完整执行, 所以资源需要在finally中手动关闭。在java7中可以自动关闭资源,这时需要使用java7的语法:

public class A {
    static void a() {
        try(
            BufferedReader br = new BufferedReader(new FileReader("A.java"));
            PrintStream ps = new PrintStream(new FileOutputStream("a.txt"));
        ) {
            /*try块*/
        } catch(IOException e) {
        }
    }
}

上面try后面有个括号,类似于方法参数列表。在try()中定义的变量可以在try、catch、finally中使用,无需提取到try之前。程序中隐含了一个自动关闭br和ps的finally块。如果你愿意,可以自己写finally

5. catch块和finally块必须出现其中一个或者两者都出现。java7之后,可以一个都不写:参见第4点

6. Runtime异常无需显示声明抛出,如果需要捕获,也可以catch。常见的runtime异常为NullPointerException、IndexOuterOfBoundsException、ArithmeticException,这些异常继承了RuntimeException

 出错会导致程序中断,感觉RuntimeException应该继承Error,但实际上继承的是Exception,好奇怪

7. 大程序中经常在catch中throw异常,throw的是包装过之前的异常的异常或者是新异常。这样利于安全性,避免暴露底层细节,而且能以另一种更易理解的方式传达给catch异常的人。比如dao层catch了“数据库连接”异常,然后经过包装成“数据库帐号密码错误”异常或者重新new一个“数据库帐号密码错误”异常再throw给service层处理。

8. java7的throw比较强大。你的方法内部throw了IOException,你可以在catch中throw Exception,而方法throws的是IOException。当然你得确定你抛出的Exception实际上真的是IOException,如:

class A {
    static void a() throws IOException {
        throw new IOException();
    }
}
class B {
    static void b() throws IOException  {//注意是IOException,java7会仔细检查e是什么类型
        try {
            A.a();
        } catch (Exception e) {
            throw e;//抛出的是Exception
        }
    }
}

9. 异常链,应用了设计模式中的职责链模式。就是一个异常包装另一个异常,把一个Exception传给异常的构造器,如

new IOException(new Exception);作用在第7点

10. 在正式发布的程序中,应该避免使用printStackTrace()处理异常,而应该要进行业务逻辑的处理,并把异常信息写进日志文件

11. 不要过度使用异常,要将业务逻辑和异常处理分离开,比如验证用户输入的合法性最好用业务逻辑来处理,不要用异常处理。一是异常处理效率慢,二是业务逻辑只用if else来判断即可,较为简单,三是尽量减少业务和异常的耦合

 

mysql与sql

1. 使用之前先把mysql服务打开(mysqld-nt.exe),以及把mysql的环境变量给加上(指定到bin目录)

2. 连接mysql: mysql -h hostname -u username -ppassword          注意-p后面没空格

     或   mysql -u username -p

3. 显示所有的数据库:       show databases;  

4. 创建数据库:        create database [IF NOT EXISTS] dbName;  IF NOT EXISTS是可选的

5. 删除数据库:        drop database dbName;

5. 切换当前数据库:        use dbName;

6. 显示当前数据库的所有表:  show tables;      

7. 显示表里的字段信息:      desc tableName;

8. 退出mysql:          quit/exit

9. windows手动mysql服务:  http://www.lc365.net/blog/b/14461/

10. mysql数据库支持两种存储机制。一种是MyISAM,这是mysql早期的默认存储机制,对事务支持不够好。第二种是InnoDB,通过建立行级锁来保证事务完整性,并以Oracle风格的共享锁来处理Select语句,系统默认启动InnoDB存储机制,如果不想使用InnoDB可以使用skip-innodb选项。在建表时可以设定存储机制:如

ENGINE=MyISAM  ENEGINE=InnoDB,如:

create table test1(id int) ENGINE=MyISAM;

11. sql分为5种类型:

  a) 查询语句,如select语句

  b) DML(Data Manipulation Language,  数据库操作语言), 主要有insert、update和delete

  c) DDL(Data Definition Language, 数据定义语言), 主要有create、alter、drop、truncate(先删除表再重新创建表,速度很快)

  d) DCL(Data Control Language, 数据控制语言), 主要有grant和revoke ----------都是设置权限的关键字

  e) 事务控制语句,主要有commit,rollback、 savepoint

12. sql不分大小写

13. 常见的数据库对象,下表摘自疯狂java讲义:

  

对象名称 对应关键字 描述
table 表就是存储数据的逻辑单元,以行和列的形式存在;列就是字段,行就是记录
数据字典  

就是系统表,存放数据库相关信息的表。系统表里的数据通常由数据库系统维护,

程序员不应该手动修改系统表以及内部数据,

程序员只可查看系统表的数据

约束 constraint 执行数据校验的规则,用于保证数据完整性的规则
视图 view 一个或多个数据表里数据的逻辑显示。视图并不存储数据
索引 index 用于提高查询性能,相当于书的目录
函数 function 用于完成一次特定的计算,具有一个返回值
存储过程 procedure

用于完成一次完整的业务处理,没有返回值,但通过传出参数将多个值

传给调用环境

触发器 trigger

相当于一个事件监听器,当数据库发生特定事件后,触发器被触发,完

成响应的处理

 14. DDL可以操作数据库对象比如create table, create index, create view。要记住,操作数据库对象的是DDL

 15. 创建表时可以设置字段默认值如: id varchar(255) default 'xxx'

 16. 可以通过子查询创建一场表,如:create table t as select * from user_inf; 这样创建的t表就具有而后user_inf表一样的字段和数据

 17. DDL常用操作:

  增加字段:  alter table tableName add(aaa varchar(255) default 'xxx', bbb varchar(255)); 或alter table tableName add aaa varchar(255);

          增加字段时要注意除非为新增的列指定默认值,否则新增额数据列不可指定非空约束

   修改字段:   alter table tableName modify xxxxx varchar(12) not null, modify article varchar(12) not null default 'abc'; mysql修改多个字段只能增加多个modify语句如:

 

   删除字段:  alter table tableName drop xxxxx, drop content;

   给表重命名: alter table tableName  rename to tt;

  MySQL的change关键字:  alter table tableName change xxx aaa varchar(20) default '998xxoo' not null;//把xxx变成aaa,并改变类型、默认值和非空约束

 18. 数据库约束

  a) NOT NULL

  b) UNIQUE

  c) PRIMARY KEY

  d) FOREIGN KEY

  e) CHECK  指定一个布尔表达式,用于指定对应列的值必须满足该表达式

  f) 单列约束

  g) 多列约束

 19. MySQL的语句中可以使用check约束,但是不会有任何作用

 20. MySQL使用information_schema数据库里的TABLE_CONSTRAINTS表来保存该数据库实例中所有的约束信息

 21. 取消非空约束:把语句中的not null 改成null 就好了

 22. UNIQUE约束: 保证指定列或指定列组不允许出现重复值,但是可以出现多个null值,因为在数据库中null不等于null。同一个表内可建多个唯一约束,,唯一约束也可由多列组成。当为某列创建唯一约束时,MySQL会为该列响应地创建唯一索引。如果不给唯一约束秦明,该唯一约束默认与列名相同。

 23. PRIMARY KEY相等等于UNIQUE加上NOT NULL。主键自增长:可以在整形字段的后边加上 auto_increment

 24. FOREIGN KEY,要注意references的是主表的主键,主键和外键的个数和类型都是一致的。一般用外键来表示一对多、多对多的关系

 25. 创建UNIQUE、PRIMARY KEY、FOREIGN KEY的语句很类似,删除这三个约束的语句也很类似。

  建立上面三个约束有两种写法:

  1) 列级约束语法:这样做只能修改一列,而且不能指定约束名称

create table teacher(
    teacher_id int primary key,
    teacher_name varchar(10) unique
);

create table student(
    student_id int primary key,
    student_name varchar(10) unique,
    teacher_id int references teacher(teacher_id)#虽然能够运行,使用列级约束语法建立外键在MySQL中无效
);

  2) 表级约束语法:可以让多列组成一个约束,并且可以给约束命名

create table if not exists teacher(
    teacher_id int,
    teacher_id2 int,
    teacher_name varchar(10),
    teacher_name2 varchar(10),
    teacher_name3 varchar(10),
    teacher_name4 varchar(10),
    teacher_name5 varchar(10), 
    constraint teacher_pk primary key(teacher_id, teacher_id2),#设置primary key
    
    unique(teacher_name, teacher_name2),#设置unique key,或者下面的
    constraint teacher_uk unique(teacher_name3, teacher_name4)
) ENGINE=INNODB;

create table student(
    student_id int primary key,
    student_name varchar(10) unique,
    teacher_id int,
    teacher_id2 int,
    
    #foreign key(teacher_id, teacher_id2) references teacher(teacher_id, teacher_id2),#设置外键,或者下面的
    constraint student_teacher_fk foreign key(teacher_id, teacher_id2) references teacher(teacher_id, teacher_id2)
) ENGINE=INNODB;

 26. 修改约束:

  

drop index unique_name;#MySQL删除unique约束的写法,一般数据库用drop constraint

alter table student
drop primary key;#删除主键约束,不需要名字

alter table student
drop foreign key studnet_teacher_fk;#删除外键约束,需要名字

#增加上面的三个约束,均可以用alter tableName add constraint语句
#修改上面的三个约束,均可以用alter tableName modify 语句

 

27. CHECK约束

  如:当然这在MySQL不起效果,仅仅是为了符合SQL标准

create table student(
    student_id int primary key,
    student_name varchar(10) unique,
    student_score float
    
    check(student_score <= 100 && student_score >=0)

) ENGINE=INNODB;

 

28. 索引是存放在模式(scheme)中的一个数据库对象,虽然索引总是从属于数据表,但它也和数据表一样术语数据库对象。创建索引的唯一作用就是加速对表的查询,索引通过使用快速路径访问方法来快速定位数据,从而减少磁盘的I/O。索引作为数据库对象,在数据字典中独立存放,但不能独立存在,必须属于某个表。MySQL使用information_schema数据库中的STATISTICS表来保存该数据库实例中的所有索引信息

29. 创建索引有两种方式

  自动:当在表上定义主键约束、唯一键约束和外键约束时,系统会为该字段创建对应的索引(约束不是索引,只不过创建约束时系统自动加上索引)

  手动:create index indexName on tableName(columnName, ...);

30. 删除索引的两种方式

  自动:删除表时,索引自动被删除

  手动: drop index indexName on tableName;

31. Oracle删除索引不需要指定表名,因为索引不需要重名。而MySQL各表中的索引可以重名,表内不可以重名,所以需要指定索引

32. 索引可以加速查询,但是需要系统开销

33. 视图看起来像数据表,但不是。它不能存储数据,而只是关联了一个查询结果(即关联了sql语句)。

  使用视图的好处:可以限制对数据的访问

          可以使复杂的查询变得简单

          提供数据的独立性(没看懂)

          提供对相同数据的不同显示(没看懂)

  使用方法:

create or replace view view_test
as
select student_id from student;
with check option;

  一般视图是不让修改视图里的数据的,所以可以在最后加上 with check option

 

 34. 自关联,一个表的外键引用了这个表自己的主键。如员工表中员工的上司id字段指向上司的id

create table forign_test
(
    foreign_id int auto_increment primary key,
    foreign_name varchar(55),
    refer_id int,
    foreign key(refer_id) references forign_test(foreign_id)
);

35. 如果想删除主表记录时也删除子表记录可以在写外键时加上 on delete cascade,如:

  foreign key(refer_id) references forign_test(foreign_id) on delete cascade

 如果想删除主表记录时,让子表记录赋值为null,可以加上 on delete set null
 (外键本身没有非空约束,所以外键可以为null,但是不能为其他主表的主键没有的值。如果想让外键必须是主表的主键的值,那就加上非空约束)

36. 多表连接查询

  多表连接查询有两种规范,SQL92和SQL99

  SQL92提供的多表连接:

    等值连接

    非等值连接(大于、小于等等)

    外连接

    广义笛卡尔积

  SQL99提供的多表连接:(提供了可读性更好的多表连接语法)

    交叉连接

    自然连接

    使用using子句的连接

    使用on子句的连接

    全外连接或左、右外连接

37. 进行多表连接查询时千万要注意不要写成笛卡尔积,效率掉渣了。除非你非得用笛卡尔积查询

38. MySQL不支持SQL92的左外、右外连接,以及SQL99的全外连接

39. 自连接,查询第34点所说的自关联表时用到的查询。把一张表当成两张表就行(两个别名)。自连接只是连接的一种用法,而不是一种连接类型。

40. 交叉连接--笛卡尔积 cross join

  如: select s.*, teacher_name from student_table s cross join teacher_table t;

41. 自然连接: 自然连接会以两个表中的同名列作为连接条件;如果没有同名列,就变成笛卡尔积

    join ... natural

    如:select s.*, teacher_name from student_table s natural join teacher_table t;

42. join ... using子句连接: 可以显式指定一列或多列同名列,如果不是同名列会报错

    如: select s.* , teacher_name from student_table s join teacher_table t using(teacher_id);

43. join ... on子句连接: join... on... on 相当等于from ... where

     如 select s.* , teacher_name from student_table s join teacher_table t on s.java_teacher > t.teacher_id;

      可以用于等值连接、非等值连接

44. 左、右。 使用on来连接条件(不可缺少)

 

select s.* , teacher_name from student_table s left join teacher_table t on s.java_teacher > t.teacher_id;
    
select s.* , teacher_name from student_table s right outer join teacher_table t on s.java_teacher < t.teacher_id;#outer可省略
    
select s.* , teacher_name from student_table s full join teacher_table t on s.java_teacher = t.teacher_id;

45. 子查询

  子查询出现在两个地方:

    1) from后边,这时被当作数据表,这种用法也被称为行内视图,因为该子查询的实质就是一个临时视图

    2) where后边

  当子查询返回一个值时,可以用 =、>、<比较

  当子查询返回多个值时,可以在子查询的括号前面用in any all,要注意三者与>、<联用时的区别

46. 集合运算

  使用集合运算,必须保证两个查询结果返回的字段数量一直而且类型一一相同。最后的结果以第一个表的字段名做为字段名

  union:并集

      如select * from teacher union select student_id, student_name from student;

  minus: 差集/余集

      用法如union,但MySQL不支持munus,可以用子查询实现:

select student_id, student_name 
from student
where (student_id, student_name) 
not in (select teacher_id, teacher_name from teacher);

  intersect:交集

    用法如union,但MySQL不支持intersect,可以用子查询实现:

select student_id, student_name
from student s
join teacher t
on (s.student_id = t.teacher_id and s.student_name = t.teacher_name);

 

    如果求交集的两个select语句都用到了where,可以这样写:

 

select student_id, student_name
from student s
join teacher t
on (s.student_id = t.teacher_id and s.student_name = t.teacher_name)
where student_id < 4;

47. mysql事务

  可以通过输入 set autocommit = 0; 来开启事务。

  临时开启事务可以使用begin;或start transaction;来开启事务。

  使用save point a;保存保存点

  使用rollback;或rollback to a;返回事务开始之前或保存点a

48. MySQL使用数据库information_schema来保存系统表

tables

schemata

views

columns

triggers

rountines:存放存储过程和函数

key_column_usage:存放带约束的键信息

table_constraint:存放带约束的表信息

statistics:存放所有的索引信息

 

JDBC编程

1. 使用executeUpdate执行DDL语句会返回0

2. java7可以使用try(){}语句来自动关闭ResultSet、PreparedStatement/Statement、Connection。java7之后,很多资源类被重写并实现了Closable接口或AutoClosable接口

3. 当不知道sql语句是查询还是更新时,可以执行Statement或PreparedStatement的exeucute方法

4. 如果设置SQL语句的参数时不知道类型,可以用PreparedStatement的setObject方法

5. PreparedStatement可以用于防止SQL注入,因为SQL写的是问号,替换参数时会把单引号给转义

6. 实例化Statement或PreparedStatement时,可以设置resultSetType的值:

    ResulSet.TYPE_FORWARD_ONLY(只能往下移动),

    ResultSet.TYPE_SCROLL_INSENSITIVE(可以自动移动,底层数据改变不影响ResultSet的内容), 

    ResultSet.TYPE_SCROLL_SENSITIVE(可以自由移动,底层数据改变影响ResultSet的内容)

  还可以设置resultSetConcurrenty的值:(控制ResultSet的并发类型)

    ResultSet.CONCUR_READ_ONLY,(默认,只读的并发模式)

    ResultSet.CONCUR_UPDATABAL(可更新的并发模式);

  可以这样实例化PreparedStatement:

PreparedStatement pstmt = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);

ResultSet rs = pstmt.executeQuery();

rs.next();
rs.previous();//往前移一位
rs.absolute(100);//定位到第100条记录
rs.first();//定位到第一条记录
rs.last();//定位到最后一条记录 rs.updateString(
1, "修改"); rs.updateRow();//这样就能在不另写一条update语句的情况下直接修改数据

 

 

7. Blob二进制长对象可以用来存储声音文件、图片文件

pstmt.setBlob(int parameterIndex, InputStream x);

Blob blob = rs.getBlob(int columnIndex);

blob.getBinaryStream();

blob.getBytes();

 

 

8. 如果不知道ResultSet中有哪些字段以及字段类型,可以通过ResultSetMeteData来获取关于ResultSet的表述信息

 1 package c13_1;
 2 
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.PreparedStatement;
 6 import java.sql.ResultSet;
 7 import java.sql.ResultSetMetaData;
 8 
 9 
10 
11 public class Main {
12     public Main() {
13         try {
14             Class.forName("com.mysql.jdbc.Driver");
15         } catch (ClassNotFoundException e1) {
16             e1.printStackTrace();
17         }
18     }
19     public void test() {
20         try (
21                 Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb",
22                         "root", "root");
23                 PreparedStatement pstmt = conn.prepareStatement("select * from article");
24                 ResultSet rs = pstmt.executeQuery();
25                 
26         ){
27             ResultSetMetaData rsmd = rs.getMetaData();//ResultSetMetaData没有实现自动关闭
28             for (int i = 1; i <= rsmd.getColumnCount(); ++i) {
29                 System.out.print(rsmd.getColumnName(i) + "(" + rsmd.getColumnTypeName(i) + ")\t");//从1开始
30             }
31             System.out.println();
32             while (rs.next()) {
33                 for (int i = 1; i <= rsmd.getColumnCount(); ++i) {
34                     System.out.print(rs.getObject(i));
35                 }
36                 System.out.println();
37             }
38         }catch (Exception e) {
39                 e.printStackTrace();
40             }
41             System.out.println("ok");
42     }
43     public static void main(String[] args) {
44 
45         new Main().test();
46         
47         
48     }
49 }
View Code

相关文章: