一 、JDBC编程
知识点总结
- JDBC 全称 Java Database Connectivity (Java 数据库连接)。一种可执行的SQL语句的 Java API.
- JDBC 为数据库开发提供了标准API ,它们只是接口,没有提供实现类—这些实现类由各数据库厂商提供实现,这些实现类即驱动程序。
- 程序员使用JDBC时只需面向标准的API 编程即可,当需要更换数据库时,只要更换不同的实现类就行,即使用同一种API 可以访问不同的数据库系统,程序通过 JDBC API 连接到关系数据库,使用SQL结构化查询语言完成对数据库的查询,更新。----面向接口编程的典型应用。
- 数据库驱动负责将JDBC 调用映射成特定的数据库调用。
- JDBC 模仿了ODBC(开放数据库连接)的设计,ODBC则 负责管理这些驱动程序。相对于JDBC 而言,JDBC更加简单,有两点优势:a:ODBC更复杂,有几个命令需要配置很多复杂的选项,JDBC简单直观。b:JDBC安全性更高,更易部署。
- 数据库实例和数据库:https://blog.csdn.net/wangyijie521/article/details/82146997
- sql脚本就是文件后缀为.sql,里面存的都是一些增删改查的sql语句,只不过放在一起执行。
- 数据库存放数据,操作数据库需要数据库管理系统DBMS(Database management System)的帮助,通常所说的数据库既包括存储用户数据的部分,也包括管理数据库的管理系统。
- 事务的概念
- DBMS是所有数据的知识库,负责数据的存储,安全,一致性,并发性,恢复和访问等操作,有一个数据字典(系统表),用于存储每个特定事务的相关信息,如名字,类型,位置。这种关于数据的数据被称为元数据。
- 对于关系型数据库而言,最基本的数据存储单元是数据表,但不仅是数据表。还有常见的数据库对象,如:数据字典,视图,索引,函数等。
- data:年月日;time:时分秒;datatime和 timestamp : 日期+时间; blob:二进制大对象,如:图片 音乐等;text:文本对象。
- 标准SQL语言通常有以下几种类型:一:查询语言 select 功能最丰富。二:DML(数据库操作语言) insert update delete 三:数据定义语言(DDL) create alter drop truncate 四:数据控制语言(DCL) grant revoke 五:事务控制语句 commit rollback savepoint
- 外键
- 数据库约束:保证数据表中数据的完整性,是强制执行的数据校验规则,包括五种完整约束:not null :非空 ;unique:唯一约束,保证列或列组合不允许出现重复值,可以多个null ;primary key:唯一标识一条记录; foreign key:外键约束,保证一个或两个数据表之间的参照完整性,从表外键参照只能是主表的主键列或唯一键列,同一个表中可以拥有多个外键.
- 索引:加速表的查询,使用快速路径访问方法定位数据,从而减少的磁盘IO。
- 视图:不能存储数据,是表中数据的逻辑显示。
- distinct:去重 ; as: 起别名。
- SQL99的连接查询:交叉连接:笛卡尔儿积; 自然连接:以相同列名作为连接条件;using子句连接:显示指定那些同名列作为连接条件;on子句连接:on后面指定一个条件;多个数据表用join; 左外右外连接
- 子查询:查询语句中嵌套另一个查询。
- 数据库的模式
- PreparedStatement 比Statement 多了三个好处:一:预编译SQL语句,性能更好;二:无需“拼接”SQL语句,编程更简单;三:防止SQL注入,安全性更好。
- RowSet
- Java7新增的RowSetFactory 和 RowSet : Java7新增了RowSetFactory 接口和 RowSetProvider类,通过RowSetFactory,就可以把应用程序与RowSet实现类分开,然后用setXXX(String xxx)设置URL,用户名,密码等来抓取数据库的数据,execute()方法执行查询。如下:
Class.forName(driver);
RowSetFactory factory = RowSetProvider.newFactory();
//JdbcRowSet 是一个可滚动。可修改的结果集,因此底层数据表中相应的记录也被修改了
JdbcRowSet jdbcRs = factory.createJdbcRowSet();
jdbcRs.setUrl(url);
jdbcRs.setUsername(user);
jdbcRs.setPassward(pass);
//设置SQL查询语句
jdbcRs.setCommand(sql);
jdbcRs.execute();
- 离线RowSet的查询分页,如下:
RowSetFactory factory = RowSetProvider.newFactory();
CachedRowSet caRs = factory.createCachedRowSet();
caRs.setPageSize(3);
caRs.populate(rs,(page-1)*3+1);
- 自动提交和开启事务恰好相反。DDL和DCL语句都会导致事务立即提交。
conn.setAutiConnit(false);//关闭自动提交,开启事务
conn.commit();//提交事务
- 批量更新:应看成单个事务,如果批量更新在执行过程中执行失败,则让事务回滚到操作之前的状态。一:关闭自动提交 二:收集更新语句 三:提交事务 四:恢复之前的提交模式。
- Java数据库简介常用代码:
public class Demo05 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 加载驱动类(加载到内存中)
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/happy", "root", "1234561");
String sql = "select * from t_user where id=?";
ps = conn.prepareStatement(sql);
// 把id大于6的记录都取出来
ps.setInt(1, 5);
rs = ps.executeQuery();
while (rs.next()) {
System.out.println(
rs.getInt(1) + "----" + rs.getString(2) + "----" + rs.getString(3) + "----" + rs.getDate(4));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 遵循:resultset-->statment-->connection这样的关闭顺序!一定要将三个trycatch块,分开写!
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
try {
if (ps != null) {
ps.close();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
类加载
(1). 知识点总结
-
类加载机制:JVM把class文件加载到内存,(并在堆上为之创建一个java.lang.Class对象)并对数据进行校验、解析和初始化,最终形成JVM可以直接使用的Java类型的过程。
-
一:加载
类加载器将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口。(外部可以通过Class 对象操作该类) -
二: 链接 将Java类的二进制代码合并到JVM的运行状态之中的过程
• 验证:
– 确保加载的类信息符合JVM规范,没有安全方面的问题。
• 准备:
– 正式为类变量(static变量)分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配
• 解析 -
三:初始化
• 初始化阶段是执行类构造器()方法的过程。类构造器()方法是由编译器自动收集
类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生的。
• 当初始化一个类的时候,如果发现其父类还没有进行过初始化、则需要先出发其父类的初始化
• 虚拟机会保证一个类的()方法在多线程环境中被正确加锁和同步。 -
类的主动引用(一定会发生类的初始化)
– new一个类的对象
– 调用类的静态成员(除了final常量)和静态方法
– 使用java.lang.reflect包的方法对类进行反射调用
– 当虚拟机启动,java Hello,则一定会初始化Hello类。说白了就是先启动main方法所在的类
– 当初始化一个类,如果其父类没有被初始化,则先会初始化他的父类 -
类的被动引用(不会发生类的初始化) – 当访问一个静态域时,只有真正声明这个域的类才会被初始化
• 通过子类引用父类的静态变量,不会导致子类初始化
– 通过数组定义类引用,不会触发此类的初始化
– 引用常量不会触发此类的初始化(常量在编译阶段就存入调用类的常量池中 -
类缓存
• 标准的Java SE类加载器可以按要求查找类,但一旦某个类被加载到类加载
器中,它将维持加载(缓存)一段时间。不过,JVM垃圾收集器可以回收
这些Class对象。 -
java.class.ClassLoader类
• 作用:
– java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,
找到或者生成其对应的字节代码,然后从这些字节代码中定义出一个
Java 类,即 java.lang.Class类的一个实例。
– 除此之外,ClassLoader还负责加载 Java 应用所需的资源,如图像文
件和配置文件等。
• 相关方法
– getParent() 返回该类加载器的父类加载器。
loadClass(String name) 加载名称为 name的类,返回的结果是 java.lang.Class类的实例。
findClass(String name) 查找名称为 name的类,返回的结果是 java.lang.Class类的实例。
findLoadedClass(String name) 查找名称为 name的已经被加载过的类,返回的结果是 java.lang.Class类的实
例。
defineClass(String name, byte[] b, int off, int len) 把字节数组 b中的内容转换成 Java 类,返回的结果是
java.lang.Class类的实例。这个方法被声明为 final的。
resolveClass(Class<?> c) 链接指定的 Java 类。
– 对于以上给出的方法,表示类名称的 name参数的值二进制表示 -
类加载器的层次结构(树状结构)
• 引导类加载器(bootstrap class loader)
– 它用来加载 Java 的核心库(JAVA_HOME/jre/lib/rt.jar,或sun.boot.class.path路径下的内容),是用原生代码来实现的,并不继承自 java.lang.ClassLoader。
– 加载扩展类和应用程序类加载器。并指定他们的父类加载器。
• 扩展类加载器(extensions class loader)
– 用来加载 Java 的扩展库(JAVA_HOME/jre/ext/*.jar,或java.ext.dirs路径下的内容) 。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java类。
– 由sun.misc.Launcher E x t C l a s s L o a d e r 实 现 • 应 用 程 序 类 加 载 器 ( a p p l i c a t i o n c l a s s l o a d e r ) – 它 根 据 J a v a 应 用 的 类 路 径 ( c l a s s p a t h , j a v a . c l a s s . p a t h 路 径 下 的 内 容 ) 来 加 载 J a v a 类 。 一 般 来 说 , J a v a 应 用 的 类 都 是 由 它 来 完 成 加 载 的 。 – 由 s u n . m i s c . L a u n c h e r ExtClassLoader实现 • 应用程序类加载器(application class loader) – 它根据 Java 应用的类路径(classpath,java.class.path 路径下的内容)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。 – 由sun.misc.Launcher ExtClassLoader实现•应用程序类加载器(applicationclassloader)–它根据Java应用的类路径(classpath,java.class.path路径下的内容)来加载Java类。一般来说,Java应用的类都是由它来完成加载的。–由sun.misc.LauncherAppClassLoader实现
• 自定义类加载器
– 开发人员可以通过继承 java.lang.ClassLoader类的方式
实现自己的类加载器,以满足一些特殊的需求。 -
类加载器的代理模式
• 代理模式
– 交给其他加载器来加载指定的类
• 双亲委托机制
– 就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次追溯,直到最高的爷爷辈的,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
– 双亲委托机制是为了保证 Java 核心库的类型安全。
• 这种机制就保证不会出现用户自己能定义java.lang.Object类的情况。
– 类加载器除了用于加载类,也是安全的最基本的屏障。
• 双亲委托机制是代理模式的一种
– 并不是所有的类加载器都采用双亲委托机制。
– tomcat服务器类加载器也使用代理模式,所不同的是它是首先尝试去加载某个类,如果找不到再代理给父类加载器。这与一般类加载器的顺序是相反的 -
JVM的类加载机制主要有如下三种:
一:全盘负责:加载器加载的某个Classs所以来和引用的其他Class也有该加载器负责。
二:父类委托
三:缓存机制:修改了Class后,必须重新启动JVM,程序所做的修改才会生效。 -
自定义类加载器。。。。