JDBC 和 类加载

一 、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 AppClassLoader实现
    • 自定义类加载器
    – 开发人员可以通过继承 java.lang.ClassLoader类的方式
    实现自己的类加载器,以满足一些特殊的需求。

  • 类加载器的代理模式
    • 代理模式
    – 交给其他加载器来加载指定的类
    • 双亲委托机制
    – 就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次追溯,直到最高的爷爷辈的,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载。
    – 双亲委托机制是为了保证 Java 核心库的类型安全。
    • 这种机制就保证不会出现用户自己能定义java.lang.Object类的情况。
    – 类加载器除了用于加载类,也是安全的最基本的屏障。
    • 双亲委托机制是代理模式的一种
    – 并不是所有的类加载器都采用双亲委托机制。
    – tomcat服务器类加载器也使用代理模式,所不同的是它是首先尝试去加载某个类,如果找不到再代理给父类加载器。这与一般类加载器的顺序是相反的

  • JVM的类加载机制主要有如下三种:
    一:全盘负责:加载器加载的某个Classs所以来和引用的其他Class也有该加载器负责。
    二:父类委托
    三:缓存机制:修改了Class后,必须重新启动JVM,程序所做的修改才会生效。

  • 自定义类加载器。。。。

猜你喜欢

转载自blog.csdn.net/qq_42349617/article/details/88124173