1、数据库连接的五种方式
#注意点:涉及到的驱动以及配置文件,有需要的请留言
package com.powernode.jdbc;
import org.junit.Test;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class ConnectionTest {
//方式一
@Test
public void test1() throws SQLException {
//1、获取driver的实现类对象
Driver driver = new com.mysql.jdbc.Driver();
String url = "jdbc:mysql://106.14.36.65:3306/test";
Properties info = new Properties();
info.setProperty("user","root");
info.setProperty("password","root");
Connection con = driver.connect(url, info);
System.out.println(con);
}
//方式二:对方式一的迭代
//下面程序不出现第三方api,更具有移植性
@Test
public void test2() throws Exception {
//1、获取driver的实现类对象,使用反射
Class aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) aClass.newInstance();
//2、设置连接的数据库
String url = "jdbc:mysql://106.14.36.65:3306/test";
//3、设置连接的用户名密码
Properties info = new Properties();
info.setProperty("user","root");
info.setProperty("password","root");
//4、建立连接
Connection connect = driver.connect(url, info);
System.out.println(connect);
}
//方式三:使用DriverManager替换Driver
@Test
public void test3()throws Exception{
//1、获取driver的实现类对象,使用反射
Class aClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) aClass.newInstance();
//2、提供连接的基本信息
String url = "jdbc:mysql://106.14.36.65:3306/test";
String user = "root";
String password = "root";
//3、注册驱动
DriverManager.registerDriver(driver);
//4、获取连接
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
//方式四:在三的基础上优化
@Test
public void test4()throws Exception{
//1、提供连接的基本信息
String url = "jdbc:mysql://106.14.36.65:3306/test";
String user = "root";
String password = "root";
//2、加载driver
Class.forName("com.mysql.jdbc.Driver");
//4、获取连接
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
//方式五:将相关的数据库连接信息声明到配置文件中,通过读取配置文件的方式获取连接
@Test
public void test5()throws Exception{
//1、读取配置文件连接数据库的基本信息
//InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties prop = new Properties();
prop.load(is);
String url = prop.getProperty("url");
String user = prop.getProperty("user");
String password = prop.getProperty("password");
//2、加载driver
Class.forName(prop.getProperty("driver"));
//3、获取连接
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
}
2、增删改查
package com.powernode.preparestatement.curd;
import com.powernode.util.JDBCUtils;
import org.junit.Test;
import java.lang.reflect.Field;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
public class PrepareStatementCurd {
//增删改查需要一个个执行才能看到实际效果
public static void main(String[] args) throws ParseException {
int row = 0;
//添加
String sql1 = "insert into customers(name,email,birth) values(?,?,?)";
SimpleDateFormat simpDate = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date parse = simpDate.parse("1996-10-02");
Date date = new Date(parse.getTime());
row = JDBC(sql1, "Jack Chen", "cxhblog@gmail.com", date);
//修改
String sql2 = "update customers set name = ? where id = ?";
row = JDBC(sql2,"Jack cxh",20);
//删除
String sql3 = "delete from customers where id = ?";
row = JDBC(sql3,20);
if(row > 0){
System.out.println("成功");
}else{
System.out.println("失败");
}
//查询,当字段别名的时候,需要对应的属性名改变
String sql4 = "select id,name,email,birth from customers where id = ?";
System.out.println(selectAll(Customers.class,sql4,18));
//查询多条
String sql5 = "select id,name,email,birth from customers where id < ?";
List<Customers> custList = get(Customers.class, sql5, 5);
custList.forEach(System.out::println);
}
//封装JDBC(只使用增删改)
public static int JDBC(String sql,Object ...args){
Connection conn = null;
PreparedStatement pres = null;
try {
//1、连接数据库
conn = JDBCUtils.getConnection();
//2、预编译sql语句,返回preparedStatement的实例 ?为占位符
pres = conn.prepareStatement(sql);
//3、填充占位符(数据库索引从1开始)
for (int i = 0; i < args.length; i++) {
pres.setObject(i + 1,args[i]);
}
//4、执行sql,返回影响行数
return pres.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
//5、关闭资源
JDBCUtils.closeResource(conn,pres);
}
return 0;
}
//添加一条记录
@Test
public void insert(){
Connection conn = null;
PreparedStatement pres = null;
try {
//1、连接数据库
conn = JDBCUtils.getConnection();
//2、预编译sql语句,返回preparedStatement的实例 ?为占位符
String sql = "insert into customers(name,email,birth) values(?,?,?)";
pres = conn.prepareStatement(sql);
//3、填充占位符(数据库索引从1开始)
pres.setString(1,"Jack Chen");
pres.setString(2,"cxhblog@gmail.com");
SimpleDateFormat simpDate = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date parse = simpDate.parse("1996-10-02");
pres.setDate(3, new Date(parse.getTime()));
//4、执行sql
pres.execute();
} catch (Exception e) {
e.printStackTrace();
} finally {
//5、关闭资源
JDBCUtils.closeResource(conn,pres);
}
}
//修改一条记录
@Test
public void update(){
Connection conn = null;
PreparedStatement pres = null;
try {
//1、连接数据库
conn = JDBCUtils.getConnection();
//2、预编译sql语句,返回preparedStatement的实例 ?为占位符
String sql = "update customers set name = ? where id = ?";
pres = conn.prepareStatement(sql);
//3、填充占位符(数据库索引从1开始)
pres.setString(1,"Jack cxh");
pres.setObject(2,19);
//4、执行sql
pres.execute();
} catch (Exception e) {
e.printStackTrace();
} finally {
//5、关闭资源
JDBCUtils.closeResource(conn,pres);
}
}
//删除一条记录
@Test
public void delete(){
Connection conn = null;
PreparedStatement pres = null;
try {
//1、连接数据库
conn = JDBCUtils.getConnection();
//2、预编译sql语句,返回preparedStatement的实例 ?为占位符
String sql = "delete from customers where id = ?";
pres = conn.prepareStatement(sql);
//3、填充占位符(数据库索引从1开始)
pres.setObject(1,19);
//4、执行sql
pres.execute();
} catch (Exception e) {
e.printStackTrace();
} finally {
//5、关闭资源
JDBCUtils.closeResource(conn,pres);
}
}
//查询一条记录
@Test
public void select(){
Connection conn = null;
PreparedStatement pres = null;
ResultSet result = null;
try {
//1、连接数据库
conn = JDBCUtils.getConnection();
//2、预编译sql语句,返回preparedStatement的实例 ?为占位符
String sql = "select id,name,email,birth from customers where id = ?";
pres = conn.prepareStatement(sql);
pres.setObject(1,18);
//4、执行,返回结果集
result = pres.executeQuery();
if(result.next()){
int id = result.getInt(1);
String name = result.getString(2);
String email = result.getString(3);
Date date = result.getDate(4);
Customers customers = new Customers(id,name,email,date);
System.out.println(customers);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//5、关闭资源
JDBCUtils.closeResource(conn,pres,result);
}
}
//封装查询,针对单个表的(单条)
@Test
public static Customers selects(String sql,Object ...args){
Connection conn = null;
PreparedStatement pres = null;
ResultSet result = null;
try {
//1、连接数据库
conn = JDBCUtils.getConnection();
//2、预编译sql语句,返回preparedStatement的实例 ?为占位符
pres = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
pres.setObject(i + 1,args[i]);
}
//4、执行,返回结果集
result = pres.executeQuery();
//获取结果集的元数据
ResultSetMetaData metaData = result.getMetaData();
//获取结果集的列数
int columnCount = metaData.getColumnCount();
if(result.next()){
Customers customers = new Customers();
for (int i = 0; i < columnCount; i++) {
//每列的value值
Object columnValue = result.getObject(i + 1);
//每列的属性名的别名
String columnLabel = metaData.getColumnLabel(i + 1);
//通过反射,给属性赋值
Field field = Customers.class.getDeclaredField(columnLabel);
field.setAccessible(true); //私有属性需要开放权限
field.set(customers,columnValue);
}
return customers;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//5、关闭资源
JDBCUtils.closeResource(conn,pres,result);
}
return null;
}
//封装查询,所有表的(单条)
@Test
public static <T>T selectAll(Class<T> clazz,String sql,Object ...args){
Connection conn = null;
PreparedStatement pres = null;
ResultSet result = null;
try {
//1、连接数据库
conn = JDBCUtils.getConnection();
//2、预编译sql语句,返回preparedStatement的实例 ?为占位符
pres = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
pres.setObject(i + 1,args[i]);
}
//4、执行,返回结果集
result = pres.executeQuery();
//获取结果集的元数据
ResultSetMetaData metaData = result.getMetaData();
//获取结果集的列数
int columnCount = metaData.getColumnCount();
if(result.next()){
T t = clazz.newInstance();
for (int i = 0; i < columnCount; i++) {
//每列的value值
Object columnValue = result.getObject(i + 1);
//每列的属性名的别名
String columnLabel = metaData.getColumnLabel(i + 1);
//通过反射,给属性赋值
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true); //私有属性需要开放权限
field.set(t,columnValue);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//5、关闭资源
JDBCUtils.closeResource(conn,pres,result);
}
return null;
}
//封装查询,所有表的(多条)
@Test
public static <T> List<T> get(Class<T> clazz,String sql,Object ...args){
Connection conn = null;
PreparedStatement pres = null;
ResultSet result = null;
try {
//1、连接数据库
conn = JDBCUtils.getConnection();
//2、预编译sql语句,返回preparedStatement的实例 ?为占位符
pres = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
pres.setObject(i + 1,args[i]);
}
//4、执行,返回结果集
result = pres.executeQuery();
//获取结果集的元数据
ResultSetMetaData metaData = result.getMetaData();
//获取结果集的列数
int columnCount = metaData.getColumnCount();
//创建集合对象
List<T> list = new ArrayList<>();
while (result.next()){
T t = clazz.newInstance();
for (int i = 0; i < columnCount; i++) {
//每列的value值
Object columnValue = result.getObject(i + 1);
//每列的属性名的别名
String columnLabel = metaData.getColumnLabel(i + 1);
//通过反射,给属性赋值
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true); //私有属性需要开放权限
field.set(t,columnValue);
}
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
//5、关闭资源
JDBCUtils.closeResource(conn,pres,result);
}
return null;
}
}
package com.powernode.util;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* @author cxhblog Email:1120710008@qq.com
* @create 2021-01-28 11:51
* @verson 1.0.0
*/
public class JDBCUtils {
/**
* @author cxhblog Email:1120710008@qq.com
* @create 15:53
* @return java.sql.Connection
*/
public static Connection getConnection() throws Exception {
//1、读取配置文件连接数据库的基本信息
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties prop = new Properties();
prop.load(is);
String url = prop.getProperty("url");
String user = prop.getProperty("user");
String password = prop.getProperty("password");
//2、加载driver
Class.forName(prop.getProperty("driver"));
//3、获取连接
Connection connection = DriverManager.getConnection(url, user, password);
return connection;
}
/**
* 关闭资源连接
* @author cxhblog Email:1120710008@qq.com
* @create 16:00
* @return void
*/
public static void closeResource(Connection conn, Statement pres){
//关闭资源
if (pres != null){
try {
pres.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
/**
* 关闭资源连接
* @author cxhblog Email:1120710008@qq.com
* @create 15:45
* @params [conn, pres, result]
* @return void
*/
public static void closeResource(Connection conn, Statement pres, ResultSet result){
//关闭资源
if (pres != null){
try {
pres.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(result != null){
try {
result.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
package com.powernode.preparestatement.curd;
import java.sql.Date;
/**
* @author cxhblog Email:1120710008@qq.com
* @create 2021-01-29 15:38
* @verson 1.0.0
*/
public class Customers {
private int id;
private String name;
private String email;
private Date birth;
public Customers() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public Customers(int id, String name, String email, Date birth) {
this.id = id;
this.name = name;
this.email = email;
this.birth = birth;
}
@Override
public String toString() {
return "Customers{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", birth=" + birth +
'}';
}
}
3、对blob类型数据的操作
package com.powernode.blob;
import com.powernode.preparestatement.curd.Customers;
import com.powernode.util.JDBCUtils;
import org.junit.Test;
import java.io.*;
import java.sql.*;
/**
* @author cxhblog Email:1120710008@qq.com
* @create 2021-02-01 15:05
* @verson 1.0.0
*/
public class BlobTest {
//插入
public static void main(String[] args){
Connection connection = null;
PreparedStatement prep = null;
FileInputStream fis = null;
try {
//连接数据库
connection = JDBCUtils.getConnection();
//预编译sql
String sql = "insert into customers(name,email,birth,photo) values(?,?,?,?)";
prep = connection.prepareStatement(sql);
//设置插入数据
prep.setObject(1,"YangMi");
prep.setObject(2,"ym@qq.com");
prep.setObject(3,"1986-02-26");
fis = new FileInputStream(new File("ym.jpg"));
prep.setObject(4,fis);
//执行sql
prep.execute();
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭资源
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
JDBCUtils.closeResource(connection,prep);
}
}
//查询
@Test
public void test(){
Connection connection = null;
PreparedStatement prep = null;
ResultSet res = null;
InputStream binaryStream = null;
FileOutputStream fos = null;
try {
//连接数据库
connection = JDBCUtils.getConnection();
//预编译sql
String sql = "select id,name,email,birth,photo from customers where id = ?";
prep = connection.prepareStatement(sql);
prep.setInt(1,26);
//执行sql
res = prep.executeQuery();
if (res.next()) {
//获取每个字段列的数据,赋值对象属性
int id = res.getInt("id");
String name = res.getString("name");
String email = res.getString("email");
Date birth = res.getDate("birth");
Customers cust = new Customers(id,name,email,birth);
System.out.println(cust);
//下载blob类型数据,以文件的格式保存到本地
Blob photo = res.getBlob("photo");
binaryStream = photo.getBinaryStream();
fos = new FileOutputStream("ym.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = binaryStream.read(buffer)) != -1) {
fos.write(buffer,0,len);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭资源
if(binaryStream != null){
try {
binaryStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
JDBCUtils.closeResource(connection,prep,res);
}
}
//批量插入(循环)
@Test
public void test1(){
Connection connection = null;
PreparedStatement prep = null;
try {
//连接数据库
connection = JDBCUtils.getConnection();
//预编译sql
String sql = "insert into goods(name) values(?)";
prep = connection.prepareStatement(sql);
long start = System.currentTimeMillis() / 1000;
//循环插入
for (int i = 0; i < 5000; i++) {
prep.setString(1,"name_" + i);
prep.execute();
}
long end = System.currentTimeMillis() / 1000;
System.out.println("插入花费时间:" + (end - start));
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(connection,prep);
}
}
//批量插入(高效方式:addBatch,executeBatch,clearBatch)
//注意:mysql默认关闭批量处理,需要设置参数开启mysql的支持,并且更新mysql驱动
//参数:?rewriteBatchedStatements=true 写在配置文件url后面,也就是(jdbc:mysql://106.14.36.65:3306/test)后
//驱动:mysql-connector-java-5.1.37-bin.jar
//设置连接不允许自动提交数据
@Test
public void test2(){
Connection connection = null;
PreparedStatement prep = null;
try {
//连接数据库
connection = JDBCUtils.getConnection();
//设置不允许自动提交数据
connection.setAutoCommit(false);
//预编译sql
String sql = "insert into goods(name) values(?)";
prep = connection.prepareStatement(sql);
long start = System.currentTimeMillis() / 1000;
//循环插入
for (int i = 0; i < 5000; i++) {
prep.setString(1,"name_" + i);
//赞存sql
prep.addBatch();
if(i % 100 == 0){
prep.executeBatch();
prep.clearBatch();
}
}
//统一提交数据
connection.commit();
long end = System.currentTimeMillis() / 1000;
System.out.println("插入花费时间:" + (end - start));
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(connection,prep);
}
}
}
4、数据库事务
#事务的ACID属性
#1、原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么不发生
#2、一致性:事务必须使数据库从一个一致性状态换到另外一个一致性状态
#3、隔离性:指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务
#是隔离的,并发执行的各个事务之间不能相互干扰
#4、持久性:指一个事务一旦被提交,它对数据库中的数据的改变就是永久性的,接下来的其他操作和数据库
#故障不应该对其有影响
package com.powernode.transation;
import com.powernode.util.JDBCUtils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* @author cxhblog Email:1120710008@qq.com
* @create 2021-02-02 14:29
* @verson 1.0.0
*/
public class TransationTest {
//普通修改
public static void main(String[] args) {
String sql1 = "update user_table set balance=900 where user=?";
JDBC(sql1,"AA");
//模拟异常
System.out.println(10 / 0);
String sql2 = "update user_table set balance=1100 where user=?";
JDBC(sql2,"BB");
System.out.println("转账成功");
}
//事务操作
@Test
public void test(){
Connection conn = null;
try {
//连接数据库
conn = JDBCUtils.getConnection();
//取消自动提交数据
conn.setAutoCommit(false);
String sql1 = "update user_table set balance=900 where user=?";
JDBC(conn,sql1,"AA");
//模拟异常
System.out.println(10 / 0);
String sql2 = "update user_table set balance=1100 where user=?";
JDBC(conn,sql2,"BB");
//提交数据
conn.commit();
} catch (Exception e) {
e.printStackTrace();
//回滚数据
try {
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
} finally {
JDBCUtils.closeResource(conn,null);
}
System.out.println("转账成功");
}
//封装JDBC(只使用增删改)
public static int JDBC(String sql,Object ...args){
Connection conn = null;
PreparedStatement pres = null;
try {
//1、连接数据库
conn = JDBCUtils.getConnection();
//2、预编译sql语句,返回preparedStatement的实例 ?为占位符
pres = conn.prepareStatement(sql);
//3、填充占位符(数据库索引从1开始)
for (int i = 0; i < args.length; i++) {
pres.setObject(i + 1,args[i]);
}
//4、执行sql,返回影响行数
return pres.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
//5、关闭资源
JDBCUtils.closeResource(conn,pres);
}
return 0;
}
//封装JDBC(事务)
public static int JDBC(Connection conn,String sql,Object ...args){
PreparedStatement pres = null;
try {
//1、预编译sql语句,返回preparedStatement的实例 ?为占位符
pres = conn.prepareStatement(sql);
//2、填充占位符(数据库索引从1开始)
for (int i = 0; i < args.length; i++) {
pres.setObject(i + 1,args[i]);
}
//3、执行sql,返回影响行数
return pres.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
//恢复为自动提交
try {
conn.setAutoCommit(true);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
//4、关闭资源
JDBCUtils.closeResource(null,pres);
}
return 0;
}
}
4、数据库并发问题
#对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,
#就会导致各种并发问题:
#脏读:对于两个事务T1, T2, T1读取了已经被T2更新但还没有被提交的字段。
#之后,若T2回滚, T1读取的内容就是临时且无效的。
#不可重复读:对于两个事务T1, T2, T1读取了一个字段,然后T2更新了该字段。
#之后, T1再次读取同一个字段,值就不同了。
#幻读:对于两个事务T1,T2,T1从一个表中读取了-个字段,然后T2在该表中插入了一些新的行。
#之后,如果T1再次读取同一一个表就会多出几行。
#数据库事务的隔离性:数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。
#一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,
# **隔离级别越高,数据一致性就越好, 但并发性越弱。**
#四种隔离级别:
#1、READ UNCOMMITTED(读未提交数据):
#描述:允许事务读取未被其他事物提交的变更脏读,不可重复读和幻读的问题都会出现
#2、READ COMMITED(读已提交数据):
#只允许事务读取已经被其它事务提交的变更,可以避免脏读,但不可重复读和幻读问题仍然可能出现
#3、REPEATABLE READ(可重复读):
#确保事务可以多次从一个字段中读取相同的值在这个事务持续期间,禁止其他事物
#对这个字段进行更新可以避免脏读和不可重复读,但幻读的问题仍然存在
#4、SERIALIZABLE(串行化):
#确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入。
#更新和删除操作.所有并发问题都可以避免,但性能十分低下.
#Oracle支持2种事务隔离级别:1,4,默认1
#Mysql支持四种事务隔离级别:默认4
package com.powernode.transation;
import com.powernode.util.JDBCUtils;
import org.junit.Test;
import java.lang.reflect.Field;
import java.sql.*;
/**
* @author cxhblog Email:1120710008@qq.com
* @create 2021-02-03 16:42
* @verson 1.0.0
*/
public class TransationTest1 {
@Test
public void select() throws Exception {
Connection conn = JDBCUtils.getConnection();
//设置隔离级别:读未提交数据(脏读)
conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
//设置隔离级别:读已提交数据
// conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
//隔离级别
System.out.println(conn.getTransactionIsolation());
//取消自动提交
conn.setAutoCommit(false);
String sql = "select user,password,balance from user_table where user = ?";
User user = selectAll(conn, User.class, sql, "CC");
System.out.println(user);
}
@Test
public void update() throws Exception {
Connection conn = JDBCUtils.getConnection();
//取消自动提交
conn.setAutoCommit(false);
String sql = "update user_table set balance = ? where user = ?";
TransationTest1.JDBC(conn, sql, 5000,"CC");
Thread.sleep(10000);
System.out.println("修改结束");
}
//封装JDBC(事务)
public static int JDBC(Connection conn,String sql,Object ...args){
PreparedStatement pres = null;
try {
//1、预编译sql语句,返回preparedStatement的实例 ?为占位符
pres = conn.prepareStatement(sql);
//2、填充占位符(数据库索引从1开始)
for (int i = 0; i < args.length; i++) {
pres.setObject(i + 1,args[i]);
}
//3、执行sql,返回影响行数
return pres.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
//4、关闭资源
JDBCUtils.closeResource(null,pres);
}
return 0;
}
//封装查询,所有表的(单条事务版)
public static <T>T selectAll(Connection conn,Class<T> clazz,String sql,Object ...args){
PreparedStatement pres = null;
ResultSet result = null;
try {
//2、预编译sql语句,返回preparedStatement的实例 ?为占位符
pres = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
pres.setObject(i + 1,args[i]);
}
//4、执行,返回结果集
result = pres.executeQuery();
//获取结果集的元数据
ResultSetMetaData metaData = result.getMetaData();
//获取结果集的列数
int columnCount = metaData.getColumnCount();
if(result.next()){
T t = clazz.newInstance();
for (int i = 0; i < columnCount; i++) {
//每列的value值
Object columnValue = result.getObject(i + 1);
//每列的属性名的别名
String columnLabel = metaData.getColumnLabel(i + 1);
//通过反射,给属性赋值
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true); //私有属性需要开放权限
field.set(t,columnValue);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//5、关闭资源
JDBCUtils.closeResource(null,pres,result);
}
return null;
}
}
5、在Mysql中设置隔离级别
#查看当前的隔离级别
SELECT @@tx_isolation;
#设置当前 mySQL 连接的隔离级别
set transaction isolation level read committed;
#设置数据库系统的全局的隔离级别
set global transaction isolation level read committed;
#下面是测试创建的用户,可忽略
#创建mysql数据库用户
create user tom identified by 'abc123';
#授予通过网络方式登录的tom用户,对所有库所有表的全部权限,密码设为abc123.
grant all privileges on *.* to tom@'%' identified by 'abc123';
#给tom用户使用本地命令行方式,授予atguigudb这个库下的所有表的插删改查的权限。
grant select,insert,delete,update on atguigudb.* to tom@localhost identified by 'abc123';
6、数据库连接池
(1)c3p0数据库连接池
package com.powernode.connection;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mchange.v2.c3p0.DataSources;
import org.junit.Test;
import java.sql.Connection;
/**
* @author cxhblog Email:1120710008@qq.com
* @Description 描述
* @create 2021-02-22 14:48
* @verson 1.0.0
*/
public class C3P0Test {
@Test
public void test1() throws Exception {
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass( "com.mysql.jdbc.Driver" ); //loads the jdbc driver
cpds.setJdbcUrl( "jdbc:mysql://106.14.36.65:3306/test" );
cpds.setUser("root");
cpds.setPassword("root");
//设置初始连接池连接数
cpds.setInitialPoolSize(10);
Connection conn = cpds.getConnection();
System.out.println(conn);
//销毁连接池
// DataSources.destroy(cpds);
}
//使用xml配置文件
static ComboPooledDataSource cpds = new ComboPooledDataSource("helloc3p0");
@Test
public void test2() throws Exception {
Connection conn = cpds.getConnection();
System.out.println(conn);
}
}
#c3p0-config.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<c3p0-config>
<named-config name="helloc3p0">
<!-- 获取提供连接的四个基本信息 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://106.14.36.65:3306/test</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 进行数据库连接池基本管理的基本信息 -->
<!-- 当数据库连接池连接数不过时,一次性申请的连接数 -->
<property name="acquireIncrement">50</property>
<!-- 数据库连接池初始化的连接数 -->
<property name="initialPoolSize">100</property>
<!-- 数据库连接池维护的最小连接数 -->
<property name="minPoolSize">50</property>
<!-- 数据库连接池维护的最大连接数 -->
<property name="maxPoolSize">1000</property>
<!-- 数据库连接池最多维护的statement数 -->
<property name="maxStatements">50</property>
<!-- 每个连接最多使用的statement数 -->
<property name="maxStatementsPerConnection">5</property>
</named-config>
</c3p0-config>
(2)dbcp数据库连接池
package com.powernode.connection;
import com.sun.deploy.util.Property;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
/**
* @author cxhblog Email:1120710008@qq.com
* @Description 描述
* @create 2021-02-22 15:41
* @verson 1.0.0
*/
public class DBCPTest {
/**
* dbcp连接池常用基本配置属性
*
* 1.initialSize :连接池启动时创建的初始化连接数量(默认值为0)
*
* 2.maxActive :连接池中可同时连接的最大的连接数(默认值为8,调整为20,高峰单机器在20并发左右,自己根据应用场景定)
*
* 3.maxIdle:连接池中最大的空闲的连接数,超过的空闲连接将被释放,如果设置为负数表示不限制(默认为8个,maxIdle不能设置太小,因为假如在高负载的情况下,连接的打开时间比关闭的时间快,会引起连接池中idle的个数 上升超过maxIdle,而造成频繁的连接销毁和创建,类似于jvm参数中的Xmx设置)
*
* 4.minIdle:连接池中最小的空闲的连接数,低于这个数量会被创建新的连接(默认为0,调整为5,该参数越接近maxIdle,性能越好,因为连接的创建和销毁,都是需要消耗资源的;但是不能太大,因为在机器很空闲的时候,也会创建低于minidle个数的连接,类似于jvm参数中的Xmn设置)
*
* 5.maxWait :最大等待时间,当没有可用连接时,连接池等待连接释放的最大时间,超过该时间限制会抛出异常,如果设置-1表示无限等待(默认为无限,调整为60000ms,避免因线程池不够用,而导致请求被无限制挂起)
*
* 6.poolPreparedStatements:开启池的prepared(默认是false,未调整,经过测试,开启后的性能没有关闭的好。)
*
* 7.maxOpenPreparedStatements:开启池的prepared 后的同时最大连接数(默认无限制,同上,未配置)
*
* 8.minEvictableIdleTimeMillis :连接池中连接,在时间段内一直空闲, 被逐出连接池的时间
*
* 9.removeAbandonedTimeout :超过时间限制,回收没有用(废弃)的连接(默认为 300秒,调整为180)
*
* 10.removeAbandoned :超过removeAbandonedTimeout时间后,是否进 行没用连接(废弃)的回收(默认为false,调整为true)
*/
@Test
public void test1() throws Exception {
BasicDataSource basic = new BasicDataSource();
basic.setDriverClassName("com.mysql.jdbc.Driver");
basic.setUrl("jdbc:mysql://106.14.36.65:3306/test");
basic.setUsername("root");
basic.setPassword("root");
Connection conn = basic.getConnection();
System.out.println(conn);
}
//使用配置文件
private static DataSource source;
static{
try {
Properties prop = new Properties();
//方式一
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("dbcp.properties");
//方式二
// FileInputStream is = new FileInputStream(new File("src/dbcp.properties"));
prop.load(is);
source = BasicDataSourceFactory.createDataSource(prop);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void test2() throws Exception {
Connection conn = source.getConnection();
System.out.println(conn);
}
}
#dbcp.properties配置文件
url=jdbc:mysql://106.14.36.65:3306/test
username=root
password=root
driverClassName=com.mysql.jdbc.Driver
(3)Druid(德鲁伊)数据库连接池(推荐使用)
package com.powernode.connection;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.Test;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
/**
* @author cxhblog Email:1120710008@qq.com
* @Description 描述
* @create 2021-02-23 9:58
* @verson 1.0.0
*/
public class DruidTest {
private static DataSource source;
static {
try {
Properties prop = new Properties();
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
prop.load(is);
source = DruidDataSourceFactory.createDataSource(prop);
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void test1() throws Exception {
Connection conn = source.getConnection();
System.out.println(conn);
}
}
#druid.properties配置文件
url=jdbc:mysql://106.14.36.65:3306/test
username=root
password=root
driverClassName=com.mysql.jdbc.Driver
7、Apache-DBUtils实现CRUD操作
#封装了针对数据库的增删改查操作
package com.powernode.dbutils;
import com.powernode.preparestatement.curd.Customers;
import com.powernode.util.JDBCUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;
import org.junit.Test;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
/**
* @author cxhblog Email:1120710008@qq.com
* @Description 描述
* @create 2021-02-23 10:21
* @verson 1.0.0
*/
public class QueryRunnerTest {
@Test
public void insert(){
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getDruidConnection();
String sql = "insert into customers(name,email,birth) values(?,?,?)";
int row = runner.update(conn, sql, "Jack Chen", "cxhblog@gmail.com", "1996-10-02");
System.out.println(row);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn,null);
}
}
//查询单条
@Test
public void query(){
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getDruidConnection();
String sql = "select id,name,email,birth from customers where id = ?";
BeanHandler<Customers> handler = new BeanHandler<>(Customers.class);
Customers customers = runner.query(conn, sql, handler, 27);
System.out.println(customers);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn,null);
}
}
//查询多条
@Test
public void queryList(){
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getDruidConnection();
String sql = "select id,name,email,birth from customers where id > ?";
BeanListHandler<Customers> handler = new BeanListHandler<>(Customers.class);
List<Customers> list = runner.query(conn, sql, handler, 25);
list.forEach(System.out::println);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn,null);
}
}
//查询单条(Map)
@Test
public void queryMap(){
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getDruidConnection();
String sql = "select id,name,email,birth from customers where id > ?";
MapHandler handler = new MapHandler();
Map<String, Object> map = runner.query(conn, sql, handler, 25);
System.out.println(map);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn,null);
}
}
//查询多条条(MapList)
@Test
public void queryMapList(){
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getDruidConnection();
String sql = "select id,name,email,birth from customers where id > ?";
MapListHandler handler = new MapListHandler();
List<Map<String, Object>> mapList = runner.query(conn, sql, handler, 25);
mapList.forEach(System.out::println);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn,null);
}
}
@Test
public void count() {
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getDruidConnection();
String sql = "select count(*) from customers";
ScalarHandler handler = new ScalarHandler();
Long count = (Long) runner.query(conn, sql, handler);
System.out.println(count);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn,null);
}
}
}