JDBC
用到的jar包
mysql-connector-java-5.1.37-bin.jar
放到和src同级的libs里面,右键Add as Library
JDBC程序编写步骤
-
注册驱动——加载Driver类
Driver driver = new Driver();
-
获取连接——得到Connection
1)jdbc:mysql://
规定好表示协议,通过jdbc的方式连接mysql
2)localhost 主机,可以是ip地址
3)3306 表示mysql监听的端口
4)mysql的连接本质就是socket连接
String url = "jdbc:mysql://localhost:3306/数据库名" //将用户名和密码放入到Properties对象 Properties properties = new Properties(); //user和password是规定好的,后面的值根据实际情况填写 properties.setProperty("user","root"); properties.setProperty("password","hsp"); //网络连接 Connection connect = driver.connect(url,properties);
-
执行增删改查——发送SQL给mysql执行
String sql = "sql语句..."; //statement 用于执行静态SQL语句并返回其生成的结果的对象 Statement statement = connect.createStatement(); //如果是dml语句,返回影响行数 int rows = statement.executeUpdate(sql);
-
释放资源——关闭相关连接
statement.close(); connect.close();
获取数据库连接的五种方式
方式一
会直接使用com.mysql.jdbc.Driver()
属于静态加载,灵活性差,依赖强
//获取Driver实现类对象
Driver driver = new com.mysql.jdbc.Driver();
String url = "jdbc:mysql://localhost:3306/数据库名";
Properties info = new Properties();
info.setProperty("user","root");
info.setProperty("password","hsp");
Connection conn = driver.connect(url,info);
System.out.println(conn);
方式二
使用反射加载Driver类,动态加载,更加灵活,减少依赖性
Class clazz = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver)clazz.newInstance();
String url = "jdbc:mysql://localhost:3306/数据库";
Properties info = new Properties();
info.setProperty("user","root");
info.setProperty("password","abc123");
Connection conn = driver.connect(url,info);
System.out.println(conn);
方式三
使用DriverManager替代Driver进行统一管理
Class<?> class = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver)class.newInstance();
String url = "jdbc:mysql://localhost:3306/数据库";
String user = "root";
String password = "hsp";
//注册Driver驱动
DriverManager.registerDriver(driver);
Connection connection = DriverManager.getConnection(url,user,password);
方式四
使用Class.forName自动完成注册驱动
源码:
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register");
}
}
静态代码块,在类加载时,会执行一次
因此注册driver的工作已经完成
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/数据库名";
String user = "root";
String password = "hsp";
Connection conn = DriverManager.getConnection(url,user,password);
※ 注:
-
mysql驱动5.1.6可以无需
Class.forName("com.mysql.jdbc.Driver");
-
从jdk1.5以后使用了jdbc4,不再需要显示调用class.forName()注册驱动而是自动调用驱动jar包下的META-INF\services\java.sql.Driver文本中的类名称去注册
-
建议还是写上
方式五
使用配置文件,连接数据库更灵活
mysql.properties
jdbc.properties
user=root
password=root
url=jdbc:mysql://localhost:3306/数据库名
driver=com.mysql.jdbc.Driver
jdbc.java
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driver = properties.getProperty("driver");
String url = properties.getProperty("url");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url,user,password);
ResultSet
表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
ResultSet对象保持一个光标指向其当前的数据行。最初,光标位于第一行之前。next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false,因此可以在while循环中使用循环来遍历结果集。
while (resultSet.next()){
// 表示SQL语句成功执行
}
用完之后要加一条
resultSet.close();
Statement
-
Statement对象,用于执行静态SQL语句并返回其生成的结果的对象
-
在连接建立后,需要对数据库进行访问,执行命令或是SQL语句,可以通过
Statement (存在SQL注入)
PreparedStatement (预处理)
CallableStatement (存储过程)
-
Statement对象执行SQL语句,存在SQL注入风险
-
SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令,恶意攻击数据库
用户名:1' or
密码:or '1'= '1
-
要防范SQL注入,只要用PreparedStatement(从Statement扩展而来)取代Statement就可以了
PreparedStatement
- PreparedStatement 执行的SQL语句中的参数用问号(?)来表示,调用PreparedStatement 对象的setXxx() 方法来设置这些参数。setXxx() 方法有两个参数,第一个参数是要设置的SQL语句中的参数的索引(从1开始),第二个是设置的SQL语句中的参数的值
- 调用executeQuery(),返回ResultSet对象
- 调用executeUpdate(),执行更新,包括增、删、修改
预处理好处:
- 不再使用+拼接sql语句,减少语法错误
- 有效的解决了sql注入问题
- 大大减少了编译次数,效率较高
用完之后要加一条
preparedStatement.close();
JDBC API
事务
- JDBC程序中当一个Connection对象创建时,默认情况下是自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
- JDBC程序中为了让多个SQL语句作为一个整体执行,需要使用事务。
- 调用Connection的setAutoCommit(false) 可以取消自动提交事务。
- 在所有的SQL语句都成功执行后,调用Connection的commit()方法提交事务
- 在其中某个操作失败或出现异常时,调用Connection的rollback()方法回滚事务
批处理
-
当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。
-
JDBC的批量处理语句包括下列方法:
addBatch() 添加需要批量处理的SQL语句或参数
executeBatch() 执行批量处理语句
clearBatch() 清空批处理包的语句
-
JDBC连接MySQL时,如果要使用批处理功能,请在url中加参数
?rewriteBatchedStatements=true
-
批处理往往和PreparedStatement一起搭配使用,可以既减少编译次数,又减少运行次数,效率大大提高
数据库连接池
方式一
//1.创建一个数据源对象
ComboPooledDataSourse comboPooledDataSourse = new ComboPooledDataSourse();
//2.通过配置文件mysql.properties获取相关连接的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//3.读取相关的属性值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver");
//4. 给数据源ComboPooledDataSourse设置相关的参数
//注意:连接管理是由ComboPooledDataSourse来管理
ComboPooledDataSourse.setDriverClass(driver);
ComboPooledDataSourse.setJdbcUrl(url);
ComboPooledDataSourse.setUser(user);
ComboPooledDataSourse.setPassword(password);
//设置初始化连接数
ComboPooledDataSourse.setInitialPoolSize(10);
//最大连接数
ComboPooledDataSourse.setMaxPoolSize(50);
Connection connection = comboPooledDataSourse.getConnection();
connection.close();
方式二
使用配置文件模板来完成
- 将c3p0提供的c3p0.config.xml拷贝到src目录下
- 该文件指定了连接数据库和连接池的相关参数
ComboPooledDataSourse comboPooledDataSourse = new ComboPooledDataSourse();
Connection connection = comboPooledDataSourse.getConnection();
德鲁伊
- 加入Druid jar包
- 加入配置文件 druid.properties,将该文件拷贝到项目的src目录
- 创建Properties对象,读取配置文件
Properties properties = new Properties();
properties.load(new FileInputStream("src\\druid.properties"));
- 创建一个指定参数的数据库连接池
DataSourse dataSourse = DruidDataSourseFactory.createDataSourse(properties);
Connection connection = dataSourse.getConnection();
Connection.close();
JDBCUtils
private static String user;
private static String password;
private static String url;
private static String driver;
static {
Properties properties = new Properties();
try {
properties.load(new FileInputStream("src\\mysql.properties"));
user = properties.getProperty("user");
password = properties.getProperty("password");
url = properties.getProperty("url");
driver = properties.getProperty("driver");
} catch (IOException e) {
//在实际开发中,我们可以这样处理
//1. 将编译异常转成运行异常
//2. 这是调用者,可以选择捕获该异常,也可以选择默认处理该异常,比较方便
throw new RuntimeException(e);
}
}
//连接数据库,返回Connection
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, password);
}
public static void close(ResultSet set, Statement statement, Connection connection) throws SQLException {
if(set != null){
set.close();
}
if(statement != null){
statement.close();
}
if(connection != null){
connection.close();
}
}
用的时候
JDBCUtilsByDruid
private static DataSourse ds;
static {
Properties properties = new Properties();
try {
properties.load(new FileInputStream("src\\druid.properties"));
ds = DruidDataSourseFactory.createDataSourse(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
return ds.getConnection();
}
//关闭连接,在数据库连接池技术中,close()不是真的断掉连接
//而是把使用的Connection对象放回连接池
public static void close(ResultSet resultSet, Statement statement, Connection connection) throws SQLException {
if(resultSet != null){
resultSet.close();
}
if(statement != null){
statement.close();
}
if(connection != null){
connection.close();
}
}
用的时候