六花酱赛高
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,局部内部类可能重名,所以N从1开始递增
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 }
- 对象的三个状态:可达、可恢复、不可达
- 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,就得知道java从1.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()方法或Runtime的loafLibrary()方法加载 第三部产生的动态链接库文件,
就可以在Java中调用这个native()方法了。
transient: Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,
我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,
可以在这个域前加上关键字transient。当一个对象被序列化的时候,
transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。
volatile: 它是被设计用来修饰被不同线程访问和修改的变量,当变量被修改时,jvm会通知其他线程该变量已修改
- Scanner实例化时可指定输入流,也可以指定文件,不只有标准输入System.in哦~
用Scanner一行一行地读取文件内容也是很方便的哦~
2. System代表当前java程序的运行平台,不能实例化。提供标准输入、输出、错误,
可以得到环境变量等系统参数
3. Runtime代表当前java的运行时环境,不能实例化,只能通过Runtime.getRuntime()
获取实例,可以得到处理器数量、空闲内存数等参数。可以另外启动一个进程来运行操作
系统的命令
4. 工具类一般以s结尾,如Arrays,Collections,java7新增的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());
-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来判断即可,较为简单,三是尽量减少业务和异常的耦合
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:存放所有的索引信息
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 }