JDBC笔记

JDBC


基本概念

(JDBC)Java DataBase Connectivity

Java 数据库连接, Java语言操作数据库

JDBC本质

官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。
各个数据库厂商去实现这套接口,提供数据库驱动jar包。
我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

使用步骤


  1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
    1. 复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
    2. 右键–>Add As Library(添加到依赖库)
  2. 注册驱动
  3. 获取数据库连接对象 Connection
  4. 定义sql
  5. 获取执行sql语句的对象 Statement
  6. 执行sql,接受返回结果
  7. 处理结果
  8. 释放资源

测试代码

import java.sql.*;

public class JdbcDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        // 获取数据库连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcstu", "root", "123456");
        // 编写sql
        String sql = "select * from demo1";
        // 获取sql执行对象
        Statement state = connection.createStatement();
        // 执行sql获取返回结果
        ResultSet rs = state.executeQuery(sql);

        // 遍历获取结果
        int id;
        String name;
        int age;
        while(rs.next()) {
            id = rs.getInt(1);
            name = rs.getString(2);
            age = rs.getInt(3);
            System.out.println(id + " " + name + " " + age);
        }
        // 释放资源
        rs.close();
        state.close();
        connection.close();
    }
}

相关对象


DriverManager: 驱动管理对象

1. 注册驱动:告诉程序该使用哪一个数据库驱动jar

static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。 
写代码使用:  Class.forName("com.mysql.jdbc.Driver");
通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
 static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
 }

	注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。

2. 获取数据库连接:

方法:static Connection getConnection(String url, String user, String password) 
参数:
	 url:指定连接的路径
		 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
		 例子:jdbc:mysql://localhost:3306/db3
		 细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称
	 user:用户名
	 password:密码 

Connection:数据库连接对象

1. 功能:
	1. 获取执行sql 的对象
		 Statement createStatement()
		 PreparedStatement prepareStatement(String sql)  
	2. 管理事务:
		开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
		提交事务:commit() 
		回滚事务:rollback() 

Statement:执行sql的对象

1. 执行sql
	1. boolean execute(String sql) :可以执行任意的sql 了解 
	2. int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
		 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。
	3. ResultSet executeQuery(String sql)  :执行DQL(select)语句

ResultSet:结果集对象,封装查询结果

 boolean next(): 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true
 getXxx(参数):获取数据
	 Xxx:代表数据类型   如: int getInt() ,	String getString()
	 参数:
		1. int:代表列的编号,从1开始   如: getString(1)
		2. String:代表列名称。 如: getDouble("balance")
		
	 使用步骤:
		1. 游标向下移动一行
		2. 判断是否有数据
		3. 获取数据

PreparedStatement:执行sql的对象

1. SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
	1. 输入用户随便,输入密码:a' or 'a' = 'a
	2. sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a' 

2. 解决sql注入问题:使用PreparedStatement对象来解决
3. 预编译的SQL:参数使用?作为占位符
4. 步骤:
	1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
	2. 注册驱动
	3. 获取数据库连接对象 Connection
	4. 定义sql
		* 注意:sql的参数使用?作为占位符。 如:select * from user where username = ? and password = ?;
	5. 获取执行sql语句的对象 PreparedStatement  Connection.prepareStatement(String sql) 
	6. 给?赋值:
		* 方法: setXxx(参数1,参数2)
			* 参数1:?的位置编号 从1 开始
			* 参数2:?的值
	7. 执行sql,接受返回结果,不需要传递sql语句
	8. 处理结果
	9. 释放资源

5. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作
	1. 可以防止SQL注入
	2. 效率更高

测试代码

import java.sql.*;

public class JdbcDemo2 {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcstu", "root", "123456");
            String sql = "select * from demo1 where age > ?";
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setInt(1, 18);
            ResultSet res = ps.executeQuery();
            while(res.next()) {
                System.out.println(res.getInt(1) +
                        " " + res.getString(2) +
                        " " + res.getInt(3));
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}

封装JDBC工具类:JdbCUtils


目的:简化书写
分析:
	1. 注册驱动也抽取
	2. 抽取一个方法获取连接对象
		 需求:不想传递参数(麻烦),还得保证工具类的通用性。
		 解决:配置文件
			jdbc.properties
				url=
				user=
				password=
	3. 抽取一个方法释放资源

JdbCUtils代码

import java.net.URL;
import java.sql.*;
import java.util.Properties;


public class JdbcUtils {
    private static String driver;
    private static String url;
    private static String username;
    private static String password;

    // 静态域初始化
    static {
        try {
            Properties props = new Properties();
            String fileName = "jdbc.properties";

            URL resource = JdbcUtils.class.getClassLoader().getResource(fileName);
            props.load(resource.openStream());

            driver = props.getProperty("driver");
            url = props.getProperty("url");
            username = props.getProperty("username");
            password = props.getProperty("password");

            // 加载驱动
            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取连接
     * */
    public static Connection getConnection() throws SQLException {
        System.out.println("获取连接");
        return DriverManager.getConnection(url, username, password);
    }
    /**
     * 释放资源
     * */
    public static void close(Statement statement, Connection connection, ResultSet resultSet) {
        if(resultSet !=null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement !=null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection !=null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        System.out.println("释放资源");
    }
    public static void close(Statement statement, Connection connection) {
        if(statement !=null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection !=null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        System.out.println("释放资源");
    }
}

测试代码

import org.example.utils.JdbcUtils;
import java.sql.*;

public class JdbcDemo3 {
    public static void main(String[] args) {
        try {
            // 获取连接
            Connection conn = JdbcUtils.getConnection();
            PreparedStatement preparedStatement = conn.prepareStatement("select * from demo1 where name = ?");
            preparedStatement.setString(1, "张三");
            ResultSet resultSet = preparedStatement.executeQuery();
            int id;
            String name;
            int age;
            // 获取数据
            while(resultSet.next()) {
                id = resultSet.getInt(1);
                name = resultSet.getString(2);
                age = resultSet.getInt(3);
                System.out.println(id + " " + name + " " + age);
            }
            // 释放资源
            JdbcUtils.close(preparedStatement, conn, resultSet);
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}

运行结果

获取连接
1 张三 15
释放资源

JDBC事务控制


1. 事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
2. 操作:
	1. 开启事务
	2. 提交事务
	3. 回滚事务
3. 使用Connection对象来管理事务
	 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
		 在执行sql之前开启事务
	提交事务:commit() 
		 当所有sql都执行完提交事务
    回滚事务:rollback() 
		 在catch中回滚事务

数据库连接池


概念

概念:一个容器(集合),存放数据库连接的容器。
	    当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

好处:
	 节约资源
	 用户访问高效

实现:
	 标准接口:DataSource   javax.sql包下的
		 方法:
			获取连接:getConnection()
			归还连接:Connection.close()。如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接了。而是归还连接

	 一般我们不去实现它,有数据库厂商来实现
		 C3P0:数据库连接池技术
		 Druid:数据库连接池实现技术,由阿里巴巴提供的

c3p0

使用步骤:
1. 导入jar包 (两个) c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar 
	不要忘记导入数据库驱动jar包
	/或者直接使用maven(添加坐标到pom.xml)
		      <dependency>
			      <groupId>c3p0</groupId>
			      <artifactId>c3p0</artifactId>
			      <version>0.9.1.2</version>
		      </dependency> 
2. 定义配置文件:
	 名称: c3p0.properties 或者 c3p0-config.xml
	 路径:直接将文件放在src目录下即可。(idea项目将配置文件放到resources目录下,否则运行时会没有配置文件报错)
	 配置文件内容(c3p0.properties为例,具体参看官方文档配置):
	 
		# turn on statement pooling
		c3p0.maxStatements=10
		# close pooled Connections that go unused for
		# more than half an hour
		c3p0.maxIdleTime=1800
		# driver class
		c3p0.driverClass=com.mysql.cj.jdbc.Driver
		#jdbcUrl
		c3p0.jdbcUrl=jdbc:mysql://localhost:3306/jdbcstu
		#user
		c3p0.user=root
		#password
		c3p0.password=123456

3. 创建核心对象 数据库连接池对象 ComboPooledDataSource
4. 获取连接: getConnection

代码:
	 //1.创建数据库连接池对象
    DataSource ds  = new ComboPooledDataSource();
    //2. 获取连接对象
    Connection conn = ds.getConnection();

测试代码

import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class C3p0Demo1 {
    public static void main(String[] args) throws SQLException {
        DataSource dataSource = new ComboPooledDataSource();
        Connection connection = dataSource.getConnection();
        String sql = "select * from demo1";
        Statement stmt = connection.createStatement();
        ResultSet rs = stmt.executeQuery(sql);
        while(rs.next()) {
            int id = rs.getInt(1);
            String name = rs.getString(2);
            int age = rs.getInt(3);
            String password = rs.getString(4);
            System.out.println(id+" "+name+" "+age+" "+password);
        }
        rs.close();
        stmt.close();
    }
}

运行结果

1 张三 15 123456
2 李思 16 111111
3 王五 19 100861

Druid

 Druid:数据库连接池实现技术,由阿里巴巴提供的
 步骤:
	1. 导入jar包 druid-1.0.9.jar
	   /或者直接使用maven(添加坐标到pom.xml)
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.2.11</version>
		</dependency>
	2. 定义配置文件:
		* 是properties形式的
		* 可以叫任意名称,可以放在任意目录下(idea项目将配置文件放到resources目录下,否则运行时会没有配置文件报错)
		* druid.properties 配置文件内容示例:
			driverClassName=com.mysql.jdbc.Driver
			url=jdbc:mysql:///jdbcstu
			username=root
			password=123456
			initialSize=5
			maxActive=10
			maxWait=3000
	3. 加载配置文件。Properties
	4. 获取数据库连接池对象:通过工厂来来获取  DruidDataSourceFactory
	5. 获取连接:getConnection
 代码:
	 //加载配置文件
    Properties pro = new Properties();
    InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
    pro.load(is);
    //获取连接池对象
    DataSource ds = DruidDataSourceFactory.createDataSource(pro);
    //获取连接
    Connection conn = ds.getConnection();

JdbcUtils(添加如下方法,其他内容同上JdbcUtils)

/**
 * @return DataSource(Druid)
 * @throws Exception
 */
public static DataSource getDataSource() throws Exception {
    // 配置
    Properties properties = new Properties();
    InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties");
    properties.load(is);

    // 获取DataSoource
    DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

    return dataSource;
}

测试代码

import domain.User;
import org.example.utils.JdbcUtils;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.List;

public class DruidDemo1 {

    public static void main(String[] args) throws Exception {
        //获取连接池
        DataSource dataSource = JdbcUtils.getDataSource();
        Connection connection = dataSource.getConnection();
        List<User> users = new LinkedList<User>();
        String sql = "select * from demo1";
        Statement stmt = connection.createStatement();
        ResultSet rs = stmt.executeQuery(sql);
        User user = new User();
        while(rs.next()) {
            int id = rs.getInt("id");
            String name = rs.getString("name");
            int age = rs.getInt("age");
            String password = rs.getString("password");
            user.setId(id);
            user.setName(name);
            user.setAge(age);
            user.setPassword(password);
            users.add(user);
        }
        System.out.println(users);

        rs.close();
        stmt.close();
        connection.close();
    }
}

运行结果

[User{id=3, name='王五', age=19, password='100861'}, User{id=3, name='王五', age=19, password='100861'}, User{id=3, name='王五', age=19, password='100861'}]

domain下的User类

public class User {

    private int id;
    private String name;
    private int age;
    private String password;

    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 int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", password='" + password + '\'' +
                '}';
    }
}

Spring JDBC


概念

 Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发

使用步骤

1.导入jar包/maven项目(修改pom.xml)
    依赖:
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>5.3.21</version>
		</dependency>
3.创建JdbcTemplate对象。依赖于数据源DataSource
	JdbcTemplate template = new JdbcTemplate(ds);
4.调用JdbcTemplate的方法来完成CRUD的操作
	update():执行DML语句。增、删、改语句
	queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合
		注意:这个方法查询的结果集长度只能是1
	queryForList():查询结果将结果集封装为list集合
		注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
	query():查询结果,将结果封装为JavaBean对象
		query的参数:RowMapper
			一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
			new BeanPropertyRowMapper<类型>(类型.class)
	queryForObject:查询结果,将结果封装为对象
		一般用于聚合函数的查询

测试代码

import domain.User;
import org.example.utils.JdbcUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.util.List;

public class JdbcTemplateDemo1
{
    private static DataSource dataSource;
    private static JdbcTemplate jdbcTemplate;

    static {
        try {
            dataSource = JdbcUtils.getDataSource();
            jdbcTemplate = new JdbcTemplate(dataSource);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) throws Exception {
        // 查询
        JdbcTemplateDemo1.queryUser();
        // 添加一个用户
        User user = new User();
        user.setId(4);
        user.setName("老王");
        user.setAge(45);
        user.setPassword("1001011");
        JdbcTemplateDemo1.addUser(user);
        // 查询
        JdbcTemplateDemo1.queryUser();
        // 修改
        JdbcTemplateDemo1.modifyUser(4, "12121212");
        // 查询
        JdbcTemplateDemo1.queryUser();
        //删除
        JdbcTemplateDemo1.delUser(4);
        // 查询
        JdbcTemplateDemo1.queryUser();
    }

//    增加
    public static void addUser(User user) {
        String sql = "insert into demo1(id, name, age, password) values(?,?,?,?)";
        int res = jdbcTemplate.update(sql, user.getId(), user.getName(), user.getAge(), user.getPassword());
        if(res > 0) {
            System.out.println("添加" + user + "成功");
        }
    }

//    删除
    public static void delUser(int userid) {
        String sql = "delete from demo1 where id = ?";
        int res = jdbcTemplate.update(sql, userid);
        if (res > 0) {
            System.out.println("删除 id:" + userid + "用户成功");
        }
    }

//    修改密码
    public static void modifyUser(int userid, String password) {
        String sql = "update demo1 set password = ? where id = ? ";
        int res = jdbcTemplate.update(sql, password, userid);
        if(res > 0) {
            System.out.println("id:" + userid + " 修改密码成功");
        }
    }

//    查询
    public static void queryUser() {
        String sql = "select * from demo1";
        List<User> users = jdbcTemplate.query(sql, new BeanPropertyRowMapper<User>(User.class));
        System.out.println("当前表数据:");
        for(User user: users) {
            System.out.println(user);
        }
    }
}

运行结果

当前表数据:
User{id=1, name='张三', age=15, password='123456'}
User{id=2, name='李思', age=16, password='111111'}
User{id=3, name='王五', age=19, password='100861'}
添加User{id=4, name='老王', age=45, password='1001011'}成功
当前表数据:
User{id=1, name='张三', age=15, password='123456'}
User{id=2, name='李思', age=16, password='111111'}
User{id=3, name='王五', age=19, password='100861'}
User{id=4, name='老王', age=45, password='1001011'}
id:4 修改密码成功
当前表数据:
User{id=1, name='张三', age=15, password='123456'}
User{id=2, name='李思', age=16, password='111111'}
User{id=3, name='王五', age=19, password='100861'}
User{id=4, name='老王', age=45, password='12121212'}
删除 id:4用户成功
当前表数据:
User{id=1, name='张三', age=15, password='123456'}
User{id=2, name='李思', age=16, password='111111'}
User{id=3, name='王五', age=19, password='100861'}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值