1 JDBC操作数据库
1.1 连接数据库
首先导入jar包到lib
public class JdbcDemo1 {public static void main(String[] args) throws ClassNotFoundException, SQLException {//1.注册驱动Class.forName("com.mysql.jdbc.Driver");//2.获取数据库连接对象Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2", "root", "123456");//3.定义sql语句String sql = "update account set balance = 500 where id = 1";//4.获取执行sql的对象 statementStatement statement = conn.createStatement();//5.执行sqlint count = statement.executeUpdate(sql);//6.处理结果System.out.println(count);//7.释放资源statement.close();conn.close();}
}
1.2 数据库相关对象详解
1.2.1DriverManager:驱动管理对象
-
注册驱动
-Class.forName("com.mysql.jdbc.Driver");
com.mysql.jdbc.Driver类中存在静态代码块
MySQL 5 之后的驱动jar包可以省略注册驱动的步骤 -
获取数据库连接
-DriverManager.getConnection("jdbc:mysql://localhost:3306/db2", "root", "password");
url语法:jdbc:mysql:// [ip地址] : [端口号] / [数据库名称]
如果连接的是本机的mysql 默认是3306 url可以简写为"jdbc:mysql:///db2"
1.2.2 Connection:数据库连接对象
- 获取用于执行sql的对象
Statement createStatement();
PreparedStatement preparedStatement(String sql);
- 管理事务
- 开启事务:void setAutoCommit(boolean autoCommit) 设置参数为false即开启事务
- 提交事务:void commit()
- 回滚事务:void rollback()
1.2.3 Statement:执行sql的对象
- 执行sql
boolean execute(String sql)
:可以执行任意sqlint executeUpdate(String sql)
:执行DML(C、U、D)语句、DDL(表、库)语句,返回值是受影响的行数。判断DML是否执行成功,返回值>0则成功。ResultSet executeQurey(String sql)
:执行DQL(R)语句
1.2.4 ResultSet:结果集对象
- 获取封装好的查询结果
-next()
:游标向前移动一行
-getXxx(int column)
:获取第column列的Xxx类型的数据 索引从1开始
-getXxx(String name)
:获取命名为name字段的Xxx类型的数据
1.2.5 PreparedStatement:
- sql注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接,会造成安全问题。
sql:-select * from user where username = 'xxxx' and password = 'a' or 'a' = 'a'
- 使用PreparedStatement可以解决sql注入问题
- 预编译的sql:参数使用?作为占位符
- sql的参数使用?作为占位符。
- 获取执行sql对象使用preparedStatement
- 给占位符赋值setXxxxx(位置编号,值),注意编号从1开始。
- 效率高,且防止sql注入,后期都用这个,不再使用Statement对象
1.3 基本操作练习
增删改
public static void main(String[] args){Connection conn = null;Statement statement = null;try{Class.forName("com.mysql.jdbc.Driver");String sql = "insert into account values(null,'王五',3000)";conn = DriverManager.getConnection("jdbc:mysql:///db2", "root", "password");statement = conn.createStatement();int count = statement.executeUpdate(sql);if(count > 0){System.out.println("添加成功");}else {System.out.println("添加失败");}}catch (ClassNotFoundException | SQLException e){e.printStackTrace();}finally {//避免空指针异常if(statement!=null){try {statement.close();}catch (SQLException e){e.printStackTrace();}}if(conn!=null){try {conn.close();}catch (SQLException e){e.printStackTrace();}}}}
查询
public static void main(String[] args){Connection conn = null;Statement statement = null;ResultSet resultSet = null;try{Class.forName("com.mysql.jdbc.Driver");String sql = "select * from account";conn = DriverManager.getConnection("jdbc:mysql:///db2", "root", "password");statement = conn.createStatement();resultSet = statement.executeQuery(sql);while(resultSet.next()){int id = resultSet.getInt(1);String name = resultSet.getString("name");double balance = resultSet.getDouble(3);System.out.println(id+ " "+ name+" "+balance);}}catch (ClassNotFoundException | SQLException e){e.printStackTrace();}finally {//避免空指针异常if(resultSet!=null){try {resultSet.close();}catch (SQLException e){e.printStackTrace();}}if(statement!=null){try {statement.close();}catch (SQLException e){e.printStackTrace();}}if(conn!=null){try {conn.close();}catch (SQLException e){e.printStackTrace();}}}}
新建一个Account类型的JavaBean
读取表到Account类型的列表中
package jdbc;import domain.Account;import java.sql.*;
import java.util.ArrayList;
import java.util.List;public class JdbcDemo2 {public List<Account> findAll(){Connection conn = null;Statement stmt = null;ResultSet rs = null;List<Account> accounts = null;try {Class.forName("com.mysql.jdbc.Driver");conn = DriverManager.getConnection("jdbc:mysql:///db2", "root", "123456");String sql = "select * from account";stmt = conn.createStatement();rs = stmt.executeQuery(sql);accounts = new ArrayList<>();Account account = null;while(rs.next()){account = new Account();int id = rs.getInt("id");String name = rs.getString("name");double balance = rs.getDouble("balance");account.setBalance(balance);account.setId(id);account.setName(name);accounts.add(account);}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}finally {if(rs != null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}}if(stmt != null){try {stmt.close();} catch (SQLException e) {e.printStackTrace();}}if(conn != null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}return accounts;}public static void main(String[] args) {List<Account> all = new JdbcDemo2().findAll();for(Account a : all){System.out.println(a);}}
}
1.4 抽取JDBC的工具类
简化代码的书写
编写jdbc配置文件,设置url、user、password、driver
jdbc.properties
url=jdbc:mysql:///db2
user=root
password=password
driver=com.mysql.jdbc.Driver
package jdbc;import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;public class JdbcUtil {private static String url;private static String user;private static String password;private static String driver;//读取配置文件 用静态代码块 只需要读取一次static {try{Properties pro = new Properties();//获取src路径下的文件的方式ClassLoader加载器ClassLoader classLoader = JdbcUtil.class.getClassLoader();URL res = classLoader.getResource("jdbc.properties");String path = res.getPath();pro.load(new FileReader(path));url = pro.getProperty("url");user = pro.getProperty("user");password = pro.getProperty("password");driver = pro.getProperty("driver");Class.forName(driver);}catch (IOException e){e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}}public static Connection getConnection() throws SQLException {return DriverManager.getConnection(url,user,password);}public static void close(Statement stmt, Connection conn){if(stmt!=null){try {stmt.close();} catch (SQLException e) {e.printStackTrace();}}if(conn!=null){try {conn.close();}catch (SQLException e){e.printStackTrace();}}}public static void close(Statement stmt, Connection conn, ResultSet rs){if(rs!=null){try{stmt.close();}catch (SQLException e){e.printStackTrace();}}if(stmt!=null){try {stmt.close();} catch (SQLException e) {e.printStackTrace();}}if(conn!=null){try {conn.close();}catch (SQLException e){e.printStackTrace();}}}
}
使用工具类
package jdbc;import domain.Account;import java.sql.*;
import java.util.ArrayList;
import java.util.List;public class JdbcDemo2 {public List<Account> findAll(){Connection conn = null;Statement stmt = null;ResultSet rs = null;List<Account> accounts = null;try {conn = JdbcUtil.getConnection();String sql = "select * from account";stmt = conn.createStatement();rs = stmt.executeQuery(sql);accounts = new ArrayList<>();Account account = null;while(rs.next()){account = new Account();int id = rs.getInt("id");String name = rs.getString("name");double balance = rs.getDouble("balance");account.setBalance(balance);account.setId(id);account.setName(name);accounts.add(account);}} catch (SQLException e) {e.printStackTrace();}finally {JdbcUtil.close(stmt,conn,rs);}return accounts;}public static void main(String[] args) {List<Account> all = new JdbcDemo2().findAll();for(Account a : all){System.out.println(a);}}
}
2 登录案例
public class JdbcDemo3 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入用户名:");String username = sc.nextLine();System.out.println("请输入密码:");String password = sc.nextLine();boolean check = login(username, password);if(check){System.out.println("登录成功");}else{System.out.println("登录失败");}}public static boolean login(String username, String password){if(username == null || password == null){return false;}Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {connection = JdbcUtil.getConnection();//注意参数两端都有单引号 因为他们是字符串String sql = "select * from user where username= ? and password= ? ";preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1,username);preparedStatement.setString(2,password);resultSet = preparedStatement.executeQuery();return resultSet.next();} catch (SQLException e) {e.printStackTrace();}finally {JdbcUtil.close(preparedStatement,connection,resultSet);}return false;}
}
3 JDBC控制事务-转账案例
使用Connection对象来管理事务
执行操作之前开事务 置为false
事务结束之后提交事务
在catch里面回滚 catch捕获的异常范围要扩大 不能仅仅时sql异常
package jdbc;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;public class JdbcDemo4 {public static void main(String[] args) {Connection conn = null;PreparedStatement pstmt1 = null;PreparedStatement pstmt2 = null;try{conn = JdbcUtil.getConnection();conn.setAutoCommit(false);String sql1 = "update account set balance = balance - ? where id = ?";String sql2 = "update account set balance = balance + ? where id = ?";pstmt1 = conn.prepareStatement(sql1);pstmt2 = conn.prepareStatement(sql2);pstmt1.setDouble(1,500);pstmt2.setDouble(1,500);pstmt1.setInt(2,2);pstmt2.setInt(2,1);pstmt1.executeUpdate();pstmt2.executeUpdate();conn.commit();}catch(Exception e){//任何异常都要回滚 所有这里不只是sql异常try {if(conn != null) conn.rollback();} catch (SQLException ex) {ex.printStackTrace();}e.printStackTrace();}finally {if(pstmt2!=null){try {pstmt2.close();} catch (SQLException e) {e.printStackTrace();}}JdbcUtil.close(pstmt1,conn);}}
}