Java DataBase Connectivity是一种用于执行SQL语句的Java API,它由一组用Java语言编写的类和接口组成。通过这些类和接口,JDBC把SQL语句发送给不同类型的数据库进行处理并接收处理结果。
提供java 操作不同数据库的技术
对Java开发人员而言是API,对数据库提供商而言是接口。
面向开发人员:作为API,JDBC为程序开发提供标准的接口。
面向数据库厂商:作为接口,让数据库厂商按标准方法来实现数据库连接与操作(数据库驱动程序)。
1.下载Jar
官网连接
(注意与自的mysql版本匹配哦)随便选择一个下载
2.引入Jar (包括jdbc 驱动程序 )
JDBC 使用步骤
? 1. 加载驱动 (只会运行一次:static)
? 2. 获得链接对象 Connection
? 3. 获得执行对象 Statement
? 4. 执行sql并获得结果集(ResultSet)
? 5. 处理结果集
public static void main(String[] args) throws SQLException {
//1.注册驱动 告诉jdbc我们使用哪一个数据库厂商的驱动
//驱动管理器专门注册驱动(需要传递一个驱动对象)
// DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver");
//2. 建立驱动连接
//url:链接数据库的地址 jdbc:mysql://localhost:3306/数据库的名字
//user:用户名
//password:密码
//面向接口编程
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/j352", "root", "");
//3.创建向数据库发送sql的statement对象
Statement st = connection.createStatement();
//4.发送sql后获得一个封装了查询结果的ResultSet对象
ResultSet rs = st.executeQuery("select * from student limit 1");
//5.解析ResultSet对象获得结果
if(rs.next()) {
System.out.println("id:"+rs.getObject("Id"));
System.out.println("name:"+rs.getObject("StudentName")); System.out.println("age:"+rs.getObject("age"));
}
//释放资源
rs.close();
st.close();
connection.close();
}
DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用
原因有2个:
>导致驱动被注册2次。
>强烈依赖数据库的驱动jar
解决办法:
注册驱动的第二种方式
Class.forName(“com.mysql.jdbc.Driver”);
static Connection getConnection(String url, String user, String password)
试图建立到给定数据库 URL 的连接。
参数说明:url 需要连接数据库的位置(网址) user用户名 password 密码
例如:getConnection(“jdbc:mysql://localhost:3306/数据库名称”, “root”, “”);
URL:SUN公司与数据库厂商之间的一种协议。
jdbc:mysql://localhost:3306/数据库名称
协议 子协议 IP : 端口号 数据库
常用数据库URL地址的写法:
Oracle写法:jdbc:oracle:thin:@localhost:1521:sid
SqlServer jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid
MySql jdbc:mysql://localhost:3306/sid
Mysql的url地址的简写形式: jdbc:mysql:///sid
常用属性:useUnicode=true&characterEncoding=UTF-8
接口的实现在数据库驱动中。所有与数据库交互都是基于连接对象的。
Statement createStatement(); //创建操作sql语句的对象
String sql = “某SQL语句”;
获取Statement语句执行平台:Statement stmt = con.createStatement();
常用方法:
int executeUpdate(String sql); --执行insert update delete语句.
ResultSet executeQuery(String sql); --执行select语句.
boolean execute(String sql); --仅当执行select并且有结果时才返回true,执行其他的语句返回false.
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取链接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc","root","root");
//3.获取代表向数据库发送sql的statement对象
Statement st = conn.createStatement();
String sql="insert into student(name,age) values('奥利给','20')";
//4.发送sql
//返回影响的行数 大于0代表执行成功
int result = st.executeUpdate(sql);
if(result>0) {
System.out.println("插入成功");
}
//5.释放资源
st.close();
conn.close();
ResultSet实际上就是一张二维的表格,我们可以调用其boolean next()方法指向某行记录,当第一次调用next()方法
时,便指向第一行记录的位置,这时就可以使用ResultSet提供的getXXX(int col)方法(与索引从0开始不同个,列从1
开始)来获取指定列的数据:
rs.next();//指向第下一行
rs.getObject(1);//获取第一行第一列的数据
常用方法:
n Object getObject(int index) / Object getObject(String name) 获得任意对象
n String getString(int index)/ String getString(String name) 获得字符串
n int getInt(int index)/int getInt(String name) 获得整形
n double getDouble(int index)/ double getDouble(String name) 获得双精度浮点型
与IO流一样,使用后的东西都需要关闭!关闭的顺序是先得到的后关闭,后得到的先关闭。
rs.close(); //结果集
stmt.close(); //statement对象
con.close(); //连接对象
public static void main(String[] args) throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取链接
Connection conn =null;
Statement st=null;
ResultSet rs=null;
try {
//2.获取链接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc","root","root");
//3.获取代表向数据库发送sql的statement对象
st = conn.createStatement();
String sql="select id,name,age from student";
//4.发送sql
rs = st.executeQuery(sql);
//定义集合封装Student数据
List<Student> list=new ArrayList<Student>();
while(rs.next()) {
//查询出来的结果封装到对象中
Student s=new Student();
s.setId(rs.getInt("id"));
s.setAge(rs.getInt("age"));
s.setName(rs.getString("name"));
list.add(s);
}
System.out.println(list);
}finally {
//5.释放资源
//关闭资源之前一定要判断
if(rs!=null) {
try {
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
//让jvm回收没有被关闭的rs对象
rs=null;
}
if(st!=null) {
try {
st.close();
}catch (Exception e) {
e.printStackTrace();
}
st=null;
}
if(conn!=null) {
try {
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
conn=null;
}
}
}
}
提交公共方法(获取连接,释放资源)
将这两方法,提到一个类中 JdbcUtils
将数据库连接url, 用户名,密码,放到文件中,把它变成可以配置的
步骤1,步骤2:
public class JdbcUtils {
static {
//1.注册驱动 告诉jdbc我们使用哪一个数据库厂商的驱动
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
// 项目一旦交付
// 公司(乙) 做项目(产品) =》 给别人做项目(甲)
// 部署(运维)-》 配置文件
public static Connection GetConnection() throws ClassNotFoundException, SQLException {
//2.通过驱动管理器获取一个链接
Connection connection = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/j352", "root", "");
return connection;
}
public static void release(Connection conn, Statement sm , ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs =null; //让jvm来回收它
}
if(sm!=null){
try {
sm.close();
} catch (SQLException e) {
e.printStackTrace();
}
sm =null; //让jvm来回收它
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn =null; //让jvm来回收它
}
}
}
步骤3: 将数据库连接url, 用户名,密码,放到文件中,把它变成可以配置的
使用properties后的代码
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/j352
username=root
password=xxx
public class JdbcUtils {
private static Properties properties = new Properties();
static {
//1.注册驱动 告诉jdbc我们使用哪一个数据库厂商的驱动
try {
//1.1 读取文件中的信息
FileInputStream in = null;
try {
in = new FileInputStream("src/jdbc.properties");
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
// 1.2 Properties对象中有一个load方法
properties.load(in); //将文件相关的信息加载到properties 对象中
Class.forName(properties.getProperty("driverClassName"));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// 项目一旦交付
// 公司(乙) 做项目(产品) =》 给别人做项目(甲)
// 部署(运维)-》 配置文件
public static Connection GetConnection() throws ClassNotFoundException, SQLException, IOException {
// 读取文件中的数据 jdbc.properties ,进行使用
//String getProperty(String key)
//2.通过驱动管理器获取一个链接
Connection connection = (Connection) DriverManager.getConnection(properties.getProperty("url"),
properties.getProperty("username"), properties.getProperty("password"));
return connection;
}
public static void release(Connection conn, Statement sm , ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs =null; //让jvm来回收它
}
if(sm!=null){
try {
sm.close();
} catch (SQLException e) {
e.printStackTrace();
}
sm =null; //让jvm来回收它
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn =null; //让jvm来回收它
}
}
}
如果执行的sql语句,是用字符串进行拼接, 就容易出sql 注入
输入时,不让它输入特殊字符 ,正则表达式限定(只输入字母或数字 )
执行sql时不用sql拼接,而使用参数化查询
public int login(String username, String pwd) {
int result = 0;
Connection conn = null; //创建连接
// Statement statement = null;
PreparedStatement pst = null;
ResultSet resultSet = null;
try {
conn = JdbcUtils.GetConnection();
// 查询
String sql = "select * from user where username=? and pwd=? ";
pst = conn.prepareStatement(sql);
pst.setString(1,username);
pst.setString(2,pwd);
System.out.println(sql);
resultSet = pst.executeQuery(sql);
if (resultSet.next()) {
result = 1;
}
} catch (ClassNotFoundException e) {
result = 2;
e.printStackTrace();
// throw new RuntimeException(e);
} catch (SQLException e) {
result = 3;
e.printStackTrace();
} catch (IOException e) {
result = 4;
e.printStackTrace();
}finally {
JdbcUtils.release(conn,pst,resultSet);
}
return result;
}
conn.setAutoCommit(false) == start transaction;
conn.commit() == commit;
conn.rollback(); == rollback;
public class TransactionDemo {
public static void main(String[] args) {
// 1. 获取连接
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try{
connection = JdbcUtils.GetConnection();
//2. 事务开启
connection.setAutoCommit(false);
String sql = "update user set age = 18 where username='admin'";
statement = connection.prepareStatement(sql);
statement.executeUpdate(); //执行sql
// int x= 1/ 0 ;
String sql2 = "update user set age = 28 where username='doubleyong'";
statement = connection.prepareStatement(sql2);
statement.executeUpdate(); //执行sql
// 3。提交事务
connection.commit();
}catch (Exception e){
//关闭事务
try {
connection.rollback();
// connection.commit();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
e.printStackTrace();
}
finally {
JdbcUtils.release(connection,statement,resultSet);
}
}
}
回滚到指定位置
savepoint = conn.setSavepoint();
public static void main(String[] args) {
// 1. 获取连接
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
Savepoint savepoint=null;
try{
connection = JdbcUtils.GetConnection();
//2. 事务开启
connection.setAutoCommit(false);
String sql = "update user set age = 66 where username='admin'";
statement = connection.prepareStatement(sql);
statement.executeUpdate(); //执行sql
//设置一个事务的回滚点
savepoint = connection.setSavepoint();
int x= 1/ 0 ;
String sql2 = "update user set age = 77 where username='doubleyong'";
statement = connection.prepareStatement(sql2);
statement.executeUpdate(); //执行sql
// 3。提交事务
connection.commit();
}catch (Exception e){
//关闭事务
try {
connection.rollback(savepoint); //回滚到指定事物点
connection.commit(); //回滚后,如何 还是有sql执行,必须 加上commit
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
e.printStackTrace();
}
finally {
JdbcUtils.release(connection,statement,resultSet);
}
}
= connection.prepareStatement(sql2);
statement.executeUpdate(); //执行sql
// 3。提交事务
connection.commit();
}catch (Exception e){
//关闭事务
try {
connection.rollback(savepoint); //回滚到指定事物点
connection.commit(); //回滚后,如何 还是有sql执行,必须 加上commit
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
e.printStackTrace();
}
finally {
JdbcUtils.release(connection,statement,resultSet);
}
}