• MySQL是一种关系数据库管理系统,是一种开源软件
• 由瑞典MySQL AB公司开发,2008年1月16号被Sun公司收购。2009年,SUN又被Oracle 收购
• MySQL软件采用双授权政策,分为社区版和商业版。由于体积小、速度快、总体拥有 成本低,尤其是开放源码特点,一般中小型网站的开发都选择MySQL作为网站数据库。
• 由于其社区版的性能卓越,搭配PHP和Apache可组成良好的开发环境。
• MySQL能够工作在众多不同的平台上
• 端口:3306
• 默认用户:root
• 字符集:默认字符集latin1,应设置为gbk或utf-8
• 安装时可以启动远程登录、创建匿名账户
• 可安装图形化操作界面,方便操作
• 安装mysql错误解决方案
• 手动删除mysql安装目录
• 重新运行配置向导MySQLInstanceConfig.exe
• 删除C:\ProgramData\MySQL目录
• 启动MySQL服务 • net start mysql
• 连接MySQL • mysql -h127.0.0.1 -uroot –p
• 退出MySQL • exit • Quit
• 关闭MySQL服务 • net stop mysql
数值类型:
• SMALLINT: 2个字节
• INT: 4个字节 // age int(10)
• INTEGER:INT的同义词
• BIGINT : 8个字节
• FLOAT : 4个字节
• DOUBLE : 8个字节 //score float(10,2)
• MySQL支持选择在该类型关键字后面的括号内指定整数值的显示宽度(例如,INT(4))。显示宽度并 不限制可以在列内保存的值的范围,也不限制超过列的指定宽度的值的显示
字符串(字符)类型
• CHAR:固定长度字符串 sex char(2)
• VARCHAR:可变长度字符串 name varchar(20)
• VARCHAR使用起来较为灵活,CHAR处理速度更快
• TEXT:非二进制大对象(字符)
• BLOB:二进制大对象(非字符)
日期/时间类型:
• DATE: YYYY-MM-DD
• DATETIME: YYYY-MM-DD HH:MM:SS
• TIMESTAMP: YYYY-MM-DD HH:MM:SS
• TIME:HH:MM:SS • YEAR:YYYY
• 主键自增 • 不使用序列,通过auto_increment
SQL语言包含4个部分:
• 数据定义语言(如create,drop,alter等语句)
• 数据查询语言(select语句)
• 数据操纵语言(insert,delete,update语句)
• 数据控制语言(如grant,revoke,commit,rollback等语句)
• 数据操纵语言针对表中的数据,而数据定义语言针对数据库或表
JDBC概述
使用JDBC完成添加/更新/删除操作
使用JDBC完成查询操作
JDBC语法总结
使用PreparedSatement完善JDBC操作
手动启动事务管理
采用分层实现JDBC案例
什么是JDBC
• JDBC(Java Data Base Connectivity,Java数据库连接)
• 是一种用于执行SQL语句的Java API,为多种关系数据库提供统一访问
• 它由一组用Java语言编写的类和接口组成
• 有了JDBC,程序员只需用JDBC API写一个程序,就可以访问所有数据库。
• 将Java语言和JDBC结合起来使程序员不必为不同的平台编写不同的应用程序,只须写 一遍程序就可以让它在任何平台上运行,这也是Java语言“编写一次,处处运行”的 优势。
• JDBC API
• 提供者:Sun公司
• 内容:供程序员调用的接口与类,集成在java.sql和javax.sql包中,如
• DriverManager类 作用:管理各种不同的JDBC驱动
• Connection接口
• Statement接口
• ResultSet接口
• JDBC 驱动
• 提供者:数据库厂商
• 作用:负责连接各种不同的数据库
• JDBC对Java程序员而言是API,对实现与数据库连接的服务提供商而言是接口模型。
三方关系
• SUN公司是规范制定者,制定了规范JDBC(连接数据库规范)
• 数据库厂商微软、甲骨文等分别提供实现JDBC接口的驱动jar包
• 程序员学习JDBC规范来应用这些jar包里的类。
JDBC访问数据库步骤
• 1:加载一个Driver驱动
• 2:创建数据库连接(Connection)
• 3 :创建SQL命令发送器Statement
• 4:通过Statement发送SQL命令并得到结果
• 5:处理结果(select语句)
• 6:关闭数据库资源
• ResultSet
• Statement
• Connection。
1.加载驱动
• 加载JDBC驱动是通过调用方法java.lang.Class.forName(),下面列出常用的几种数据库驱动程序 加载语句的形式 :
• Class.forName(“oracle.JDBC.driver.OracleDriver”);//使用Oracle的JDBC驱动程序
• Class.forName(“com.microsoft.JDBC.sqlserver.SQLServerDriver”);//使用SQL Server的JDBC驱 动程序
• Class.forName(“com.ibm.db2.JDBC.app.DB2Driver”);//使用DB2的JDBC驱动程序
• Class.forName(“com.mysql.JDBC.Driver”);//使用MySql的JDBC驱动程序
2.创建数据库连接
• 与数据库建立连接的方法是调用DriverManager.getConnection(String url, String user, String password )方法
• Connection conn=null;
• String url=“jdbc:oracle:thin:@localhost:1521:orcl”;
• String user=“scott"; • String password=“tiger";
• conn = DriverManager.getConnection(url, user, password);
3.创建Statement并发送命令
• Statement对象用于将 SQL 语句发送到数据库中,或者理解为执行sql语句
• 有三种 Statement对象:
• Statement:用于执行不带参数的简单SQL语句;
• PreparedStatement(从 Statement 继承):用于执行带或不带参数的预编译SQL语句;
• CallableStatement(从PreparedStatement 继承):用于执行数据库存储过程的调用。
4.处理ResultSet结果
• ResultSet对象是executeQuery()方法的返回值,它被称为结果集,它代表符合SQL语句条件的 所有行,并且它通过一套getXXX方法(这些get方法可以访问当前行中的不同列)提供了对这 些行中数据的访问。
• ResultSet里的数据一行一行排列,每行有多个字段,且有一个记录指针,指针所指的数据行 叫做当前数据行,我们只能来操作当前的数据行。我们如果想要取得某一条记录,就要使用 ResultSet的next()方法 ,如果我们想要得到ResultSet里的所有记录,就应该使用while循环。
• ResultSet对象自动维护指向当前数据行的游标。每调用一次next()方法,游标向下移动一行。
• 初始状态下记录指针指向第一条记录的前面,通过next()方法指向第一条记录。循环完毕后 指向最后一条记录的后面。
5.关闭数据库资源
• 作为一种好的编程风格,应在不需要Statement对象和Connection对象时显式地关闭它们。关 闭Statement对象和Connection对象的语法形式为:
• public void close() throws SQLException
• 用户不必关闭ResultSet。当它的 Statement 关闭、重新执行或用于从多结果序列中获取下一 个结果时,该ResultSet将被自动关闭。
• 注意:要按先ResultSet结果集,后Statement,最后Connection的顺序关闭资源,因为 Statement和ResultSet是需要连接是才可以使用的,所以在使用结束之后有可能其他的 Statement还需要连接,所以不能先关闭Connection。
业务:输入用户名和密码,判断登录是否成功
缺陷:存在SQL注入风险
stmt = conn.createStatement();
String sql=“select * from t_user where userno=’” +userno+"’ and password=’"+upwd+"’";
rs = stmt.executeQuery(sql); System.out.println(sql);
if(rs.next()){ System.out.println(" 登 录 成 功 , 欢 迎 您 “); }else{ System.out.println(” 用 户 名 或 者 密 码 错 误 , 请 重 新 登 录 "); }
• PreparedStatement 接口继承 Statement接口
• 如果需要多次执行一个SQL语句,可以使用PreparedStatement对象。在创建 PreparedStatement对象时,通过传递不同参数值多次执行PreparedStatement对象,可 以得到多个不同的结果。
• 优势:执行效率高、代码可读性强、安全性高
• 该对象用Connection的prepareStatement()方法创建。如:
• pstmt=conn.prepareStatement(“insert into student values(?,?,? )”);
• pstmt.setString(1, “小明");
• pstmt.setInt(2, 27);
• pstmt.setFloat(3, 85);
• pstmt.executeUpdate();
• PreparedStatement接口中的主要方法
• void setString (int parameterIndex, String x)
• void setFloat (int parameterIndex, float x)
• void setInt (int parameterIndex, int x)
• void setDate (int parameterIndex, java.sql.Date x)
• void setDouble (int parameterIndex, double x)
• ResultSet executeQuery () //返回单结果集,通常用于SELECT语句
• boolean execute () //返回布尔值,通常用于insert,update,delete语句
• int executeUpdate () //返回操作影响的行数,通常用于insert,update,delete语句
• 在JDBC中,事务操作缺省是自动提交。
• 一条对数据库的更新表达式代表一项事务操作
• 操作成功后,系统将自动调用commit()提交,否则调用rollback()回滚
• 在JDBC中,事务操作方法都位于接口java.sql.Connection中
• 可以通过调用setAutoCommit(false)来禁止自动提交。
• 之后就可以把多个数据库操作的表达式作为一个事务,在操作完成后调用commit()来进行整 体提交,
• 倘若其中一个表达式操作失败,都不会执行到commit(),并且将产生响应的异常;
• 此时就可以在异常捕获时调用rollback()进行回滚,回复至数据初始状态
• 事务结束的边界是commit或者rollback方法的调用
• 事务开始的边界则不是那么明显了,它会开始于组成当前事务的所有statement中的 第一个被执行的时候。
• 完成对雇员数据的多种操作
• 查询所有雇员
• 按照编号查询雇员
• 添加雇员
• 删除雇员
• 具体实现
• 定义包结构
• 定义实体类Employee
• 定义EmployeeDao接口
• 定义EmployeeDaoImpl
• 抽取BaseDao
• 测试
作业
• 使用JDBC的基本过程是什么?
• 建立一个student表,包含学号id、姓名name、年龄age、生日birthday,系别 department。编写java类接收来自客户端的学生信息,并存入数据库表中;把数据库 表中所有记录输出到屏幕。
• 建立一个books表,包含书号bookid、书名name、出版社press、作者author,价格 price和出版日期pdate字段。编写Java类实现对books表的分别按书号、书名、作者的 查询,并且实现信息的插入和删除。、
JDBC(Java Database Connection)为java开发者使用数据库提供了统一的编程接口,它由一组java类和接口组成。是java程序与数据库系统通信的标准API。JDBC API 使得开发人员可以使用纯java的方式来连接数据库,并执行操作。
sun公司由于不知道各个主流商用数据库的程序代码,因此无法自己写代码连接各个数据库,因此,sun公司决定,自己提供一套api,凡是数据库想与Java进行连接的,数据库厂商自己必须实现JDBC这套接口。而数据库厂商的JDBC实现,我们就叫他此数据库的数据库驱动。
范围跟数据库的流程:
加载JDBC驱动程序
建立于数据库的连接
发送SQL查询
得到查询结果
Driver接口由数据库厂家提供,对于java开发者而言,只需要使用Driver接口就可以了。
在编程中要连接数据库,必须先装载特定厂商的数据库驱动程序。不同的数据库有不同的装载方法。
驱动:就是各个数据库厂商实现的Sun公司提出的JDBC接口。 即对Connection等接口的实现类的jar文件
装载MySql驱动
Class.forName(“com.mysql.jdbc.Driver”);
装载Oracle驱动
Class.forName(“oracle.jdbc.driver.OracleDriver”);
先把jar包加进来
驱动的名字
DriverManager是JDBC的管理层,作用于用户和驱动程序之间。
DriverManager跟踪可用的驱动程序,并在数据库和相应的驱动程序之间建立连接。
Connection 与特定数据库的连接(会话),在连接上下文中执行 SQL 语句并返回结果。
DriverManager的getConnection()方法建立在JDBC URL中定义的数据库Connection连接上
连接MYSQL数据库:
Connection con = DriverManager.getConnection(“jdbc:mysql://host:port/database”,“user”,“password”);
连接ORACLE数据库:
Connection con = DriverManager.getConnection(“jdbc:oracle:thin:@host:port:databse”,“user”,“password”);
其实内部是,建立了socket连接
用于执行静态 SQL 语句并返回它所生成结果的对象。
三种Statement类:
Statement:
由createStatement创建,用于发送简单的SQL语句。(不带参数的)
PreparedStatement:
继承自Statement接口,由prepareStatement创建,用于发送含有一个或多个输入参数的sql语句。PreparedStatement对象比Statement对象的效率更高,并且可以防止SQL注入。我们一般都用PreparedStatement.
CallableStatement:
继承自PreparedStatement 。由方法prePareCall创建,用于调用存储过程。
常用的Statement方法:
execute():运行语句,返回是否有结果集。
executeQuery():运行select语句,返回ResultSet结果集。
executeUpdate():运行insert/update/delete操作,返回更新的行数。
处理参数不方便
容易发生sql注入的危险
一旦发生了sql注入(1=1)外界就会轻易的能够修改你的数据库
?占位符,一会需要的时候把参数传进去,避免拼字符串的时候别人sql注入
加时间
Statement执行SQL语句时返回ResultSet结果集。
ResultSet提供的检索不同类型字段的方法,常用的有:
getString():获得在数据库里是varchar、char等数据类型的对象。
getFloat():获得杂数据库里是Float类型的对象。
getDate():获得在数据库里面是Date类型的数据。
getBoolean():获得在数据库里面是Boolean类型的数据
ResultSet Statement Connection
灵活指定SQL语句中的变量
PreparedStatement
对存储过程进行调用
CallableStatement
运用事务处理
Transaction
Batch
对于大量的批处理,建议使用Statement,因为PreparedStatement的预编译空间有限,当数据量特别大时,会发生异常。
事务基本概念
一组要么同时执行成功,要么同时执行失败的SQL语句。是数据库操作的一个执行单元!
事务开始于:
连接到数据库上,并执行一条DML语句(INSERT、UPDATE或DELETE)。
前一个事务结束后,又输入了另外一条DML语句。
事务结束于:
执行COMMIT或ROLLBACK语句。
执行一条DDL语句,例如CREATE TABLE语句;在这种情况下,会自动执行COMMIT语句。
执行一条DCL语句,例如GRANT语句;在这种情况下,会自动执行COMMIT语句。
断开与数据库的连接。
执行了一条DML语句,该语句却失败了;在这种情况中,会为这个无效的DML语句执行ROLLBACK语句。
事务的四大特点(ACID)
atomicity(原子性)
表示一个事务内的所有操作是一个整体,要 么全部成功,要么全失败;
consistency(一致性)
表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前的状态;
isolation(隔离性)
事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。
durability(持久性)
持久性事务完成之后,它对于系统的影响是永久性的。
事务隔离级别从低到高:
读取未提交(Read Uncommitted)
读取已提交(Read Committed)
可重复读(Repeatable Read)
序列化(serializable)
用于存储大量的文本数据
大字段有些特殊,不同数据库处理的方式不一样,大字段的操作常常是以流的方式来处理的。而非一般的字段,一次即可读出数据。
Mysql中相关类型:
TINYTEXT最大长度为255(21–1)字符的TEXT列。
TEXT[(M)]最大长度为65,535(22–1)字符的TEXT列。
MEDIUMTEXT最大长度为16,777,215(23–1)字符的TEXT列。
LONGTEXT最大长度为4,294,967,295或4GB(24–1)字符的TEXT列。
用于存储大量的二进制数据
大字段有些特殊,不同数据库处理的方式不一样,大字段的操作常常是以流的方式来处理的。而非一般的字段,一次即可读出数据。
Mysql中相关类型:
TINYBLOB最大长度为255(25–1)字节的BLOB列。
BLOB[(M)]最大长度为65,535(26–1)字节的BLOB列。
MEDIUMBLOB最大长度为16,777,215(27–1)字节的BLOB列。
LONGBLOB最大长度为4,294,967,295或4GB(28–1)字节的BLOB列。
取出来
clob和blob都是通过流!
使用资源文件存储数据库连接信息
mysqlDriver=com.mysql.jdbc.Driver
mysqlURL=jdbc:mysql://localhost:3306/testjdbc
mysqlUser=root
mysqlPwd=123456
oracleDriver=oracle.jdbc.driver.OracleDriver
oracleURL=jdbc:oracle:thin:@localhost:1521:orcl
oracleUser=scott
oraclePwd=tiger
关于数据库的信息可以封装
ORM(Object Relationship Mapping)的基本思想
表结构跟类对应; 表中字段和类的属性对应;表中记录和对象对应;
让javabean的属性名和类型尽量和数据库保持一致!
一条记录对应一个对象。将这些查询到的对象放到容器中(List,Set,Map)
加一个object数组
通过数组封装了一条记录信息
如果要多条,可以把obj数组再做封装,封装到list中
用list把map套进去
容器套容器
map里面套一个map
list里面套list
我们希望设计一个可以实现对象和SQL自动映射的框架,但是整体用法和设计比Hibernate简单。砍掉不必要的功能。
会穿插使用设计模式
将对象对应成sql语句,执行sql,插入数据库中
删除
根据对象主键的值,生成sql,执行,从库中删除
修改
根据对象需要修改属性的值,生成sql,执行
从sql到对象
根据结果分类:
多行多列:List
一行多列:Javabean
一行一列:
普通对象:Object
数字:Number
Query接口:负责查询(对外提供服务的核心类)
QueryFactory类:负责根据配置信息创建query对象
TypeConvertor接口:负责类型转换
TableContext类:负责获取管理数据库所有表结构和类结构的关系,并可以根据表结构生成类结构。
DBManager类:根据配置信息,维持连接对象的管理(增加连接池功能)
工具类:
JDBCUtils封装常用JDBC操作
StringUtils封装常用字符串操作
JavaFileUtils封装java文件操作
ReflectUtils封装常用反射操作
ColumnInfo 封装表中一个字段的信息(字段类型、字段名、键类型)
Configuration 封装配置文件信息
TableInfo 封装一张表的信息
针对SORM框架的说明:
核心思想:使用简单、性能高、极易上手!
配置文件:目前使用资源文件、后期项目复杂后可以增加XML文件配置和注解。
类名由表名生成,只有首字母大写有区别,其他无区别
Java对象的属性由表中字段生成,完全对应
目前,只支持表中只有一个主键,联合主键不支持
使用工厂模式统计管理Query的创建
使用克隆模式提高Query对象的创建效率
连接池(Connection Pool)
就是将Connection对象放入List中,反复重用!
连接池的初始化:
事先放入多个连接对象。
从连接池中取连接对象
如果池中有可用连接,则将池中最后一个返回。同时,将该连接从池中remove,表示正在使用。
如果池中无可用连接,则创建一个新的。
关闭连接
不是真正关闭连接,而是将用完的连接放入池中。
正在使用的是什么数据库、项目的src(以后根据数据库生成的类就放在这下面)、包名
获取配置信息,根据信息维持连接对象的管理
根据配置信息内容,构建一个配置对象
连接
这样的话吧,tableinfo里面全部都有内容了
生成属性源码、set/get源码
刚刚实现了生成属性get/set源码
接下来生成整个java类源码
把表的所有列都取出来存放到列表中,然后调用刚刚写好的fieldgetset方法生成类的属性信息
接下来开始拼接我们的源码
因为要拼接包信息,所以我们去配置类中找一下
要获得内容很简单,调用我们写好的方法后源码就来了
现在要把这些字符串写到指定的类中
要使用流
写到什么地方?怎么获取这个路径,从配置信息中获取
把包路径中的.替换成
还需要在这个路径后面再加一个斜杠然后把类名加上
测试下,表都来了
打印个日志把
把测试代码迁移到TableContext.java
加个bonus
这个方法什么时候调用呢?在项目启动的时候
增删改 从java 对象到关系数据库
查 从数据库到对象
属性是null的就不用存了
首先把对象存到表中
生成Sql语句
需要表名
不为空的字段,属性传进来
还需要参数
拼成sql语句
测试
相对较复杂的一些查询
雇员的个人信息以及部门所在地
、
vo包
放一些值对象
独立的再写一个javabean
查询一个数字
number是包装类的所有的父类都可以用这个包装,返回完了之后可以随意的转型
查询这一块要做一个优化,让代码更灵活
把可以共用的DML方法放到父类中,子类中只写特殊的地方
删除也是与mysql本身关系不大,到抽象类中挪动
delete insert
queryNumber queryRows queryObject
query.java本身还可以做优化
模板方法模式!
hibernate的内部也有这样的回调机制,能够使得我们执行更加灵活更加复杂的查询
创建query对象的工厂类
对象有了,初始化这个对象的时候也要有
这样配置信息就读取到了这个
加载这个类
QueryFactory单例模式!!
通过这个创建query对象
把连接数在配置文件中配置一下
然后在bean里面加一个这样的内容
set/get
读配置文件的时候也要初始化一下
初始化连接数
要做1000次这样的查询
加载jar包、db.properties
用的时候就这么简单!
增加、查询
来个删除
修改
查
】刚刚查了其中一个值现在要查一行记录
改完后再发布一次!
大于有问题
由于数据库里面某些数据为空导致的!
再发布一次
链表查询
建一个vo
对应复杂的查询
根据id直接返回对象
8 ↩︎
16 ↩︎
24 ↩︎
32 ↩︎
8 ↩︎
16 ↩︎
24 ↩︎
32 ↩︎