JDBC
JDBC - java连接数据库的统一驱动
JDBC的使用
jar包的支持:
- java.sql
- javax.sql
- mysql-conneter-java… 连接驱动(必须)
环境搭建
Mysql创建数据库表
CREATE TABLE users(
id INT PRIMARY KEY,
`name` VARCHAR(40);
`password` VARCHAR(40);
email VARCHAR(60),
birthday DATE
);
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(1,'张三','123456','zs@qq.com','2020-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(2,'李四','123456','ls@qq.com','2020-01-01');
INSERT INTO users(id,`name`,`password`,email,birthday)
VALUES(3,'王五','123456','ww@qq.com','2020-01-01');
SELECT * FROM users;
导入数据库依赖
<!--mysql的驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
IDEA中连接数据库
将时区设置为上海(默认UTC全球标准时间)否则会报Server returns invalid timezone错误
JDBC 固定步骤:
- 加载驱动
- 连接数据库,代表数据库
- 向数据库发送SQL的对象Statement : CRUD
- 编写SQL (根据业务,不同的SQL)
- 执行SQL
- 关闭连接
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class TestJdbc {
public static void main(String[] args) throws Exception {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "123456";
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库connection对象代表数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.向向数据库发送SQL的对象Statement,PreparedStatement : CRUD
Statement statement = connection.createStatement();
//4.编写sql语句
String sql = "select * from users";
//5.执行语句
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println("id="+resultSet.getObject("id"));
System.out.println("name="+resultSet.getObject("name"));
System.out.println("password="+resultSet.getObject("password"));
System.out.println("email="+resultSet.getObject("email"));
System.out.println("birthday="+resultSet.getObject("birthday"));
}
//6.关闭连接,释放资源(一定要做) 先开后关
resultSet.close();
statement.close();
connection.close();
}
}
预编译SQL
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class TestJdbc2 {
public static void main(String[] args) throws Exception {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "123456";
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
//3.编写sql
String sql = "insert into jdbc.users (id, name, password, email, birthday) values (?,?,?,?,?);";
//4.预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,4);//给第一个占位符,赋值为4
preparedStatement.setString(2,"伊泽瑞尔");
preparedStatement.setString(3,"123456");
preparedStatement.setString(4,"ez@qq.com");
preparedStatement.setString(5,"2020-06-22");
//5.执行sql
int i = preparedStatement.executeUpdate();
if (i>0){
System.out.println("插入成功");
}
//6.关闭资源
preparedStatement.close();
connection.close();
}
}
prepareStatement与Statement的区别
1、Statement用于执行静态SQL语句,在执行时,必须指定一个事先准备好的SQL语句。
2、PrepareStatement是预编译的SQL语句对象,sql语句被预编译并保存在对象中。被封装的sql语句代表某一类操作,语句中可以包含动态参数“?”,在执行时可以为“?”动态设置参数值。
3、使用PrepareStatement对象执行sql时,sql被数据库进行解析和编译,然后被放到命令缓冲区,每当执行同一个PrepareStatement对象时,它就会被解析一次,但不会被再次编译。在缓冲区可以发现预编译的命令,并且可以重用。
4、PrepareStatement可以减少编译次数提高数据库性能。
事务
要么都成功,要么都失败!
ACID原则:保证数据的安全。
开启事务
事务提交 commit()
事务回滚 rollback()
关闭事务
转账案例:
A:1000
B:1000
A(900) --100–> B(1100)
如果中间出问题,转账失败则回滚事务。
创建account表
CREATE TABLE ACCOUNT(
id INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(40),
money FLOAT
);
INSERT INTO ACCOUNT(`name`,money) VALUES('A',1000);
INSERT INTO ACCOUNT(`name`,money) VALUES('B',1000);
INSERT INTO ACCOUNT(`name`,money) VALUES('C',1000);
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class TestJDBC3 {
public static void main(String[] args) {
//配置信息
//useUnicode=true&characterEncoding=utf-8 解决中文乱码
String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
String username = "root";
String password = "123456";
Connection connection = null;
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库
DriverManager.getConnection(url,username,password);
//3.通知数据库开启事务,false表示开启
connection.setAutoCommit(false);
String sql = "update account set money = money-100 where name = 'A'";
connection.prepareStatement(sql).executeUpdate();
//制造错误
//int i = 1/0;
String sql2 = "update account set money = money+100 where name = 'B'";
connection.prepareStatement(sql2).executeUpdate();
connection.commit();//以上两条sql语句都执行成功就提交事务
}catch (Exception e){
//如果出现异常,就通知数据库回滚事务
try {
connection.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
在sql和sql2语句中间,出现错误,则sql2就不执行了,那么A的钱少了,B的钱也没有增多,转账失败,这时候回滚事务,回滚到转账操作之前。
将int i = 1/0 注释,不出现错误。执行。