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的对象 statement
Statement statement = conn.createStatement();
//5.执行sql
int 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);
}
}
}