0 数据库驱动(应用程序 和 数据库厂商之间相互交互的中间人):
1 JDBC(SUN公司提供的java操作各种数据库的规范)
2 准备数据脚本 见附件User.rar
3 本机中安装好mysql,细节见本博客另一篇文章 mysql基础知识
4 常用数据库URL地址写法:
Oracle—jdbc:oracle:thin:@localhost:1521:dbname
MySql—jdbc:mysql://localhost:3306/dbname
SqlServer—jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=dbname
5 JDBC常用到的类介绍:
a) DriverManager: 加载驱动,并创建与数据库的链接
常用到方法如下:
方法 | 功能 | 说明 |
registerDriver(new Driver()) | 加载具体数据库驱动 | 不推荐,会导致驱动程序加载两次导致内存中会有两个Driver对象(查看Driver的源代码) |
Class.forName(“com.mysql.jdbc.Driver”) | 加载具体数据库驱动,取代上面方法 | 不会导致驱动对象在内存中重复出现; 程序仅仅只需要一个字符串,不需要import驱动的API,即依赖具体的驱动。 |
DriverManager.getConnection(url, user, password) | 获取数据库连接 |
b) Connection 代表数据库的链接 ,客户端与数据库所有交互都是通过connection对象完成。
常用方法如下:
方法 | 说明 |
createStatement() | 创建向数据库发送sql的statement对象 |
prepareStatement(sql) | 创建向数据库发送预编译sql的PrepareSatement对象 |
prepareCall(sql) | 创建执行存储过程的callableStatement对象 |
setAutoCommit(boolean autoCommit) | 设置事务是否自动提交 |
commit() | 在链接上提交事务 |
rollback() | 在此链接上回滚事务 |
c) Statement: 用于向数据库发送SQL语句
常用方法如下:
方法 | 说明 |
execute(String sql) | 用于向数据库发送任意sql语句 |
executeQuery(String sql) | 只能向数据发送查询语句 |
executeUpdate(String sql) | 只能向数据库发送insert、update或delete语句 |
addBatch(String sql) | 把多条sql语句放到一个批处理中 |
executeBatch() | 向数据库发送一批sql语句执行 |
d) ResultSet: 代表Sql语句的执行结果,ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据
常用方法如下:
方法 | 说明 |
getObject(int index) | |
getObject(string columnName) | |
getString(int index) | |
getString(String columnName) |
e) 数据库字段类型和对应JDBC方法对应:
SQL类型 | Jdbc对应的方法 | 返回类型 |
bit | getBoolean() | boolean |
tinyint | getByte() | byte |
smallint | getShort() | short |
int | getInt() | int |
bigint | getLong() | long |
char,varchar,longvarchar | getString() | string |
text(clob) blob | getColb() getBlob() | clob blob |
date | getDate() | java.sql.date |
time | getTime() | java.sql.time |
timestamp | getTimestamp() | java.sql.timeStamp |
6 JDBC释放资源时:
a) 捕获异常后一定要抛出,给调用者一个提醒
b) finally内关闭jdbc连接资源时,按照从小到大的顺序依次关闭,每一个关闭都要用try catch包裹,保证关闭时即使出现异常也能让JVM继续执行下去,关闭别的资源
见如下写法:
public static void delete() throws ClassNotFoundException{
String url = "jdbc:mysql:///jdbc1";
String username = "root";
String password = "root";
Class.forName("com.mysql.jdbc.Driver");
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try{
conn = DriverManager.getConnection(url,username,password);
st = conn.createStatement();
String sql = "delete from user where id=2";
st.executeUpdate(sql);
}catch(Exception e){
// 出现异常后,将此异常抛出给调用者
throw new RuntimeException(e);
}finally{
if(rs!=null)
{
try{
rs.close();
}catch(Exception e){
e.printStackTrace();
}
rs = null;
}
if(st!=null)
{
try{
st.close();
}catch(Exception e){
e.printStackTrace();
}
st = null;
}
if(conn!=null){
try{
conn.close();
}catch(Exception e){
e.printStackTrace();
}
conn = null;
}
}
}
7 JDBC防止SQ注入攻击:
7.1 使用类PreperedStatement的好处如下:
a) 使用类PreperedStatement可以避免SQL注入的问题
b) Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。
c) PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。
并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。
7.2 使用类PreperedStatement进行CRUD写法: --->给参数赋值时,参数起始位置从1开始
查询写法:
String sql = "select * from user where username=?";
st = conn.prepareStatement(sql);
st.setString(1, user.getUsername());
rs = st.executeQuery();
if(rs.next()){ dosomething....}
插入 修改 删除写法:
sql = "insert into user(username,password,email) values(?,?,?)";// 插入 修改 删除语句
//给参数赋值
st = conn.prepareStatement(sql);
st.setString(1, user.getUsername());
st.setString(2, user.getPassword());
st.setString(3, user.getEmail());
// 执行 插入/修改/删除语句
st.executeUpdate();
8 JDBC获取插入数据后返回的数据库主键:
使用关键词 RETURN_GENERATED_KEYS, 代码如下:
public static void main(String[] args) throws SQLException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
String sql ="insert into user(name,password,email,birthday) values(?,?,?,?)";
st = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);//通知jdbc程序返回数据库的主键
st.setString(1, "aaaa");
st.setString(2, "1233");
st.setString(3, "zm@sina.com");
st.setDate(4, new java.sql.Date(new Date().getTime()));
st.executeUpdate();
返回的数据仅仅是新增数据后的DB分配的主键,因此直接获取第一个位置的数据即可得到主键
rs = st.getGeneratedKeys();
if(rs.next()){
System.out.println("主键为:" + rs.getInt(1));
}
}finally{
// 释放语句
JdbcUtils.release(rs, st, conn);
}
}