一、JDBC概述
JDBC:Java DataBase Connectivity(Java连接数据库的标准。SUN制定的)
JDBC和数据库的驱动的关系:JDBC是规范,抽象层,数据库驱动是具体的实现。
JDBC规范由一些抽象类和接口组成,一般放在java.sql.*或javax.sql.*包中(JDK中带)
需要jar包: mysql-connector-java-5.0.8-bin.jar
二、JDBC编码的步骤
准备:把数据库的驱动加入到构建路径中
例:
--------------------------------------------------------------------------------------------
public class JdbcDemo1 {
public static void main(String[] args) throws SQLException {
// 1、加载驱动程序并注册驱动: DriverManage
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
// 2、获取与数据库的连接: Connection 注: 第一个参数URL: 不同的数据库是不同的,具体看数据库的文档
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day14", "root", "123456");
// 3、得到代表SQL语句的对象,并发送SQL给数据库: Statement
Statement stmt = conn.createStatement();
// 4、如果有查询结果,得到封装了查询结果的对象: ResultSet
ResultSet rs = stmt.executeQuery("select ID,NAME,PASSWORD,EMAIL,BIRTHDAY from USERS");
// 5、遍历结果
while(rs.next()){
System.out.println("----------------");
System.out.println(rs.getObject("ID"));
System.out.println(rs.getObject("NAME"));
System.out.println(rs.getObject("PASSWORD"));
System.out.println(rs.getObject("EMAIL"));
System.out.println(rs.getObject("BIRTHDAY"));
}
// 6、释放占用的资源 注: 最后使用的资源最先关
rs.close();
stmt.close();
conn.close();
}
}
--------------------------------------------------------------------------------------------
三、JDBC中常用接口和类的详细讲解
1、DriverManager
作用:注册驱动,得到数据库的连接
注册驱动:
DriverManager.registDriver(new com.mysql.jdbc.Driver());(不可取)
原因:1、严重依赖具体的数据库驱动。(高内聚,低耦合)
2、会导致驱动注册2遍。(实现的接口new的时候注册一遍,接口中静态代码块也一遍)
替代方案:Class.forName("com.mysql.jdbc.Driver");
获取数据库的连接:
方式1:static Connection getConnection(String url,String user,String password):
url:数据库的连接串。
mysql:jdbc:mysql://localhost:3306/day14数据库名
或者jdbc:mysql:///day14(连接本地默认端口上的mysql数据库)
user:数据库的用户名
password:数据库的密码
方式2:static Connection getConnection(String url,Properties info)
方式3:static Connection getConnection(String url)
注: 在配置文件中要注意&的转义: &或设置为CDATA区
例:
-----------------------------------------------------------------------------------------------------
方式1(常用):
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day14", "root", "密码");
方式2:
Properties info = new Properties();
info.setProperty("user", "root"); // 注意: 查阅mysql文档,键必须是user 和 password
info.setProperty("password", "密码");
Connection conn = DriverManager.getConnection("jdbc:mysql:///day14", info);
方式3:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day14?user=root&password=密码");
-----------------------------------------------------------------------------------------------------
常用数据库URL的写法
2、Connection
所有与数据库交互都必须建立在连接的基础上
常用方法:
createStatement():创建向数据库发送sql的statement对象。
prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象。
prepareCall(sql):创建执行存储过程的callableStatement对象。
setAutoCommit(boolean?autoCommit):设置事务是否自动提交。
commit() :在链接上提交事务。
rollback() :在此链接上回滚事务。
3、Statement
作用:代表着SQL语句
常用的方法:
ResultSet executeQuery(String sql): sql是DQL语句
int executeUpdate(String sql): sql是DML语句。或者是没有返回结果的DDL也可以。返回值,代表着语句影响到的行数。
boolean execute(String sql): sql可以是任何的sql语句。如果有结果集返回,返回true。否则返回false。
例:
--------------------------------------------------------------------------------------------------------------------------
public void addUser(User user) {
Connection conn = null;
Statement stmt = null;
try{
conn = JdbcUtil.getConnection();
stmt = conn.createStatement();
stmt.executeUpdate("insert into user (username,password,email,birthday) " +
"values('"+user.getUsername()+"','"+user.getPassword()+"','"+user.getEmail()+"','"
+user.getBirthday().toLocaleString()+"')");
}catch(Exception e){
throw new DaoException(e);
}finally{
JdbcUtil.release(null, stmt, conn);
}
}
--------------------------------------------------------------------------------------------------------------------------
4、ResultSet
boolean next():下移一行
boolean previous():上移一行
void absolute(int row):第一行的记录就是1
void beforeFirst():移动到第一行的前面
void afterLast():移动到最后一行的后面
常用数据类型转换表:
-------------------------------------------------------------------------------------------------------------------------------
ResultSet rs = stmt.executeQuery("select ID,NAME,PASSWORD,EMAIL,BIRTHDAY from USERS");
// 创建一个集合,用来存放user
List<Users> users = new ArrayList<Users>();
while(rs.next()){
System.out.println("----------------");
// 方式1 建议使用: 明确直观
// System.out.println(rs.getObject("ID"));
// System.out.println(rs.getObject("NAME"));
// System.out.println(rs.getObject("PASSWORD"));
// System.out.println(rs.getObject("EMAIL"));
// System.out.println(rs.getObject("BIRTHDAY"));
// 方式2 编写框架时很有用
// System.out.println(rs.getObject(1)); // 第一列
// System.out.println(rs.getObject(2));
// System.out.println(rs.getObject(3));
// System.out.println(rs.getObject(4));
// System.out.println(rs.getObject(5));
// 实际开发中是要用来封装到javaBean中的 如下:
Users u = new Users();
u.setID(rs.getInt("ID"));
u.setNAME(rs.getString("NAME"));
u.setPASSWORD(rs.getString("PASSWORD"));
u.setEMAIL(rs.getString("EMAIL"));
u.setBIRTHDAY(rs.getDate("BIRTHDAY")); // 注:rs.getDate()得到的sql.date 是 util.date的子类 此处自动向上转型
users.add(u);
}
-------------------------------------------------------------------------------------------------------------------------------
5、释放资源
注: 最后使用的资源最先关
6、连接数据库的模版代码:
-------------------------------------------------------------------------------------------------------------------------------
public class JdbcDemo4 {
public static void main(String[] args) {
List<Users> users = new ArrayList<Users>();
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day14", "root", "123456");
stmt = conn.createStatement();
rs = stmt.executeQuery("select ID,NAME,PASSWORD,EMAIL,BIRTHDAY from users");
while(rs.next()){
Users u = new Users();
u.setID(rs.getInt("ID"));
u.setNAME(rs.getString("NAME"));
u.setPASSWORD(rs.getString("PASSWORD"));
u.setEMAIL(rs.getString("EMAIL"));
u.setBIRTHDAY(rs.getDate("BIRTHDAY"));
users.add(u);
}
}catch(Exception e){
throw new RuntimeException(e);
}finally{
if(rs!=null){
try{
rs.close();
}catch(SQLException e){
e.printStackTrace();
}
rs = null;
}
if(stmt!=null){
try{
stmt.close();
}catch(SQLException e){
e.printStackTrace();
}
stmt = null;
}
if(conn!=null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}
conn = null;
}
}
}
}
-------------------------------------------------------------------------------------------------------------------------------
六、SQL的注入及防范
SQL 注入是用户利用某些系统没有对输入数据进行充分的检查,从而进行恶意破坏的行为。
1、statement存在sql注入攻击问题,例如登陆用户名采用' or 1=1 or name=‘
2、对于防范 SQL 注入,可以采用PreparedStatement取代Statement。
防止SQL的注入方法: MD5加密 和 PreparedStatement(预置语句)
PreparedStatement:(尽量使用它,就不要再使用Statement)
作用:
1、预编译SQL语句,数据库执行效率高。
2、防止SQL注入
3、支持参数占位符"?"
例:
------------------------------------------------------------------------------------------------
public void addUser(User user) {
Connection conn = null;
PreparedStatement stmt = null;
try{
conn = JdbcUtil.getConnection();
// 使用占位符代表字段
stmt = conn.prepareStatement("insert into user(username,password,email,birthday) values(?,?,?,?)");
// 设置各个占位符代表的字段的值,从1开始
stmt.setString(1, user.getUsername());
stmt.setString(2, user.getPassword());
stmt.setString(3, user.getEmail());
// 注意 : 要先将util的日期设置为毫秒值,再有sql获取, 而不能强转: 因为util是父类,不能强转成子类sql
stmt.setDate(4, new java.sql.Date(user.getBirthday().getTime()));
stmt.executeUpdate();
}catch(Exception e){
throw new DaoException(e);
}finally{
JdbcUtil.release(null, stmt, conn);
}
}
----------------------------------------------------------------------------------------------------------------------------------------