######JDBC
- Java DataBase Connectivity,java数据库连接,实际上jdbc就是java中的一套和数据库交互的api(application program interface)
#####为什么使用JDBC
- 因为java需要连接多种数据库,为了避免每一种数据库都学习一套新的api,sun公司定义了一套jdbc的标准(接口,方法声明),各个数据库厂商根据此接口写方法的实现(数据库驱动),这样java程序员只需要掌握jdbc接口中方法的调用,掌握一套方法可以连接任何数据库,一套遵循jdbc标准的代码可以连接任何数据库
外网:maven.aliyun.com
pom.xml引入jar包地址<dependencies></dependencies>
#####如何使用jdbc
1.创建maven工程
2.maven外网搜索mysql的jar包,放到工程中的pom.xml
操作如下:
//1.注册驱动
// com.mysql.jdbc.Driver
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接对象
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "lf215000");
System.out.println(connection);
//3.创建SQL执行对象
Statement statement = connection.createStatement();
//4.执行SQL
// String sql="create table if not exists jdbct1(id int,name varchar(10))";//如果不存在则创建
String sql="drop table if exists jdbct1";
statement.execute(sql);
System.out.println("执行成功!");
//5.关闭资源
statement.close();
connection.close();
#####执行SQL对象的方法
- execute(sql) 此方法返回值代表是否有结果集(boolean),此方法可以执行任意SQL,但推荐执行DDL(数据定义语言 create drop alter truncate)
- executeUpdate(sql) 可以执行增删改操作 此方法返回值为int类型表示生效行数
- executeQuery(sql) 执行查询SQL语句 返回值为结果集
######数据库类型和java类型对比
mysql java
int getint
varchar getString
float/double getfloat/getDouble
datetime/timestamp getDate
######resultSet获取数据的两种方式
1.getString(字段名)
2.getString(查询结果字段的位置) 从1开始
######Properties属性配置对象
- 用于读取*.properties配置文件里面的数据 (键值对方式 key:value)
- 使用方式:
//创建属性对象
Properties properties = new Properties();
//得到文件输入流
InputStream inputStream = Demo04.class.getClassLoader().getResourceAsStream("jdbc.properties");
//把文件加载到属性随对象中
properties.load(inputStream);
//读取数据
String name = properties.getProperty("name");
//读取出来的任何内容都是字符串类型
String age = properties.getProperty("age");
System.out.println("name="+name+" age="+age);
####DBCP数据库连接池
- DataBase Connection Pool
- 为什么使用数据库连接池:
如果没有数据库连接池,web服务器每次和数据交互都需要建立一个连接,使用完关闭连接,如果有一万次交互,则会有 一万次连接开启和关闭,频繁的开关连接非常浪费资源,使用数据库连接池,可以设置初始连接数量和最大连接数量,每次和数据的交互都会从连接池中去连接用完后再次放回连接池中而不是断开来凝结,这样就可以起到连接数据库重用的作用,避免了资源浪费
- 如何使用数据库连接池
######Statement和PreparedStatement
- PrepareStatement 预编译的SQL执行对象
1.好处是可以避免SQL注入 因为在编译时已经把SQL的逻辑规定,不会因为替换进去的内容改变逻辑
2.如果SQL中涉及变量相比Statement字符串拼接方式,代码可读性提高,并且不容易出错
3.如果涉及批量执行多条SQL时 使用PreparedStatement执行效率较高
- 如果SQL中没有变量用Statement 有变量用PreparedStatement
#######批量操作
- Statement批量
statement = connection.prepareStatement(sql);
for (int i=0;i<100;i++) {
statement.setString(1, "name"+i);
statement.setString(2, "admin"+i);
//添加批量操作
statement.addBatch();
if(i%20==0) {
//执行批量操作
statement.executeBatch();
//清空执行过的SQL
statement.clearBatch();
}
}
//执行批量操作,收尾残余
statement.executeBatch();
#######事务
1.开启和关闭自动提交
connection.setAutoCommit(false/true);
2.提交事务
connection.commit();
3.回滚
connection.rollback();
- 实现转账:
超人 500 蝙蝠侠 5000
蝙蝠侠给超人转账2000
执行第一次成功
执行第二次成功
执行第三次失败 提示余额不足 并且回滚
create table jdbc_person (id int,name varchar(10),money int);
insert into jdbc_person values(1,'超人',500),(2,'蝙蝠侠',5000);
- 代码参考demo08.java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
public class Demo08 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
connection = DBUtils.getConnection();
statement = connection.createStatement();
//开启事务(关闭自动提交)
connection.setAutoCommit(false);
//准备转账SQL
String sql1 = "update jdbc_person set money=money-2000 where id=2";
String sql2 = "update jdbc_person set money=money+2000 where id=1";
//执行转账
statement.executeUpdate(sql1);
statement.executeUpdate(sql2);
//查询蝙蝠侠剩余的钱是否大于等于0
String sql3 = "select money from jdbc_person where id=2";
resultSet = statement.executeQuery(sql3);
while(resultSet.next()) {
int money = resultSet.getInt("money");
if(money>=0) {//钱够
connection.commit();
System.out.println("转账成功");
}else {//钱不够
connection.rollback();
System.out.println("转账失败");
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtils.close(connection, statement, resultSet);
}
}
}
######获取自增主键的值
create table team (id int primary key auto_increment,name varchar(10));
create table player(id int primary key auto_increment,name varchar(10),tid int);
null
例:
姚明 火箭队
球队表
id name
1 火箭队
球员表
id name tid
姚明 1
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
public class Demo09 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入球队名称:");
String teamName = sc.nextLine();
System.out.println("请输入球员名称:");
String playerName = sc.nextLine();
sc.close();
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = DBUtils.getConnection();
//先查询球队是否存在如果存在需要得到球队的id
String s = "select id from team where name=?";
statement = connection.prepareStatement(s);
statement.setString(1,teamName);
resultSet=statement.executeQuery();
int teamId=-1;
while(resultSet.next()) {
//从数据库中查询报讯teamid
teamId = resultSet.getInt("id");
}
if(teamId==-1) {//之前没有保存过球队
String sql="insert into team values(null,?)";
//多次创建statement会警告未关闭,在警告前先关闭上一个statement
statement.close();
statement = connection.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
statement.setString(1, teamName);
statement.executeUpdate();
//获取自增主键
resultSet.close();
resultSet = statement.getGeneratedKeys();
while(resultSet.next()) {
teamId=resultSet.getInt(1);
}
}
//之前保存过球队
//插入球员
String sql1 = "insert into player values(null,?,?)";
statement = connection.prepareStatement(sql1);
statement.setString(1, playerName);
statement.setInt(2, teamId);
statement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtils.close(connection, statement, resultSet);
}
}
}
#####源数据
- 源数据指 数据库和表的相关信息
例:
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
/**
* 源数据(数据库基础信息或表基础信息)
* @author BARCA球王=Andrew Feng
* @version 1.0
* @see
* @since
*/
public class Demo10 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
connection = DBUtils.getConnection();
statement = connection.createStatement();
//获取数据库源数据对象
DatabaseMetaData metaData = connection.getMetaData();
System.out.println("驱动版本"+metaData.getDriverVersion());
System.out.println("用户名"+metaData.getUserName());
System.out.println("连接地址"+metaData.getURL());
System.out.println("数据库名称"+metaData.getDatabaseProductName());
//获取表的元数据
resultSet = statement.executeQuery("select * from emp");
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
//得到表的字段
int columCount = resultSetMetaData.getColumnCount();
//得到字段名
for(int i=0;i<columCount;i++) {
String name = resultSetMetaData.getColumnName(i+1);
String type = resultSetMetaData.getColumnTypeName(i+1);
System.out.println(name+":"+type);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtils.close(connection, statement, resultSet);
}
}
}