一 JDBC概述
Java提供的一套用来操作数据库的接口
二 如何获取数据库的连接
1.获取数据库连接的必要条件
/*
1.保证mysql的服务是正常运行的
2.保证mysql的账号密码是对的
3.保证mysql的驱动版本是可以使用的
*/
2.方式一:Driver
//多态 Driver driver = new com.mysql.jdbc.Driver(); /* connect(String url, Properties info) url : mysql数据的地址 jdbc:mysql://localhost:3306/atguigu jdbc:mysql: 协议 localhost :mysql所在服务器的地址(ip地址) 3306 :端口号 atguigu :库名 info : 存储了用户名和密码的集合(Properties) */ String url = "jdbc:mysql://localhost:3306/myemployees"; Properties properties = new Properties(); //注意:key的值是死的不能乱写 properties.setProperty("user","root");//mysql账号 properties.setProperty("password","123321");//mysql密码 Connection connection = driver.connect(url,properties); System.out.println(connection);
3.方式二:DriverManager
//1.创建Driver对象 Driver driver = new com.mysql.jdbc.Driver(); //2.注册Driver DriverManager.registerDriver(driver); //3.通过DriverManager获取连接对象 /* getConnection(String url,String user, String password) url:mysql的连接地址 user:mysql的账户 password:mysql的密码 */ Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myemployees", "root", "123321"); System.out.println(connection); //1.让com.mysql.jdbc.Driver类进行类加载 Class.forName("com.mysql.jdbc.Driver"); //2.通过DriverManager获取连接对象 Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myemployees", "root", "123321"); System.out.println(connection);
4.方式三:读取配置文件
配置文件:jdbc.properties
username=root
password=123321
url=jdbc:mysql://localhost:3306/myemployees
driverClass=com.mysql.jdbc.Driver
代码
String url = ""; String username=""; String password=""; String driverClass=""; //通过读取配置文件中的内容赋值 //1.创建Properites对象 Properties properties = new Properties(); //2.创建流 FileInputStream fis = new FileInputStream("jdbc.properties"); //3.加载流 properties.load(fis); //4.读取配置文件中的内容 url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); driverClass = properties.getProperty("driverClass"); //5.关闭资源 if (fis != null){ fis.close(); } Class.forName(driverClass); Connection connection = DriverManager.getConnection(url, username, password); System.out.println(connection);
5.Properites
/* Properties: 说明: 1.Properties的父类中Hashtable 2.Properties的K,V类型是String 3.可以通过Properties读取配置文件中的内容。 */ public class PropertiesDemo { /* 通过Properties读取配置文件中的内容 */ @Test public void test() throws IOException { //1.创建Properties的对象 Properties properties = new Properties(); //2.加载流 FileInputStream fis = new FileInputStream("jdbc.properties"); properties.load(fis); //3.读取配置文件中的内容 String username = properties.getProperty("username"); System.out.println("username=" + username); //4.关资源 if (fis != null){ fis.close(); } } }
三 对数据库增删改查操作
/* 通过JDBC对数据进行增,删,改,查的操作 CREATE TABLE stu( id INT, NAME VARCHAR(20) ) */ public class CRUDDemo { /* 查询 */ @Test public void test4() throws Exception { List<Stu> stu = getStu(); for (Stu s : stu) { System.out.println(s); } } /* 获取stu中所有的数据 */ public List<Stu> getStu() throws Exception { //1.获取连接对象 Connection connection = JDBCUtils.getConnection(); //2.预编译 PreparedStatement ps = connection.prepareStatement("select id,name from stu where id=?"); ps.setInt(1,1); //3.执行sql语句 ResultSet resultSet = ps.executeQuery();//查询语句使用该方法返回一个结果集 List<Stu> list = new ArrayList<Stu>(); //4.遍历 while(resultSet.next()){//resultSet.next() :是否有下一条数据。 /* getInt(int columnIndex) :根据字段的位置获取数据 getInt(String columnLabel) :根据字段的名字获取数据 */ int id = resultSet.getInt("id"); String name = resultSet.getString("name"); //一条数据就是一个对象 Stu stu = new Stu(id, name); //将对象存放到集合中 list.add(stu); } //5.关闭资源 JDBCUtils.close(connection,ps,resultSet); //6.返回集合对象(集合中都是数据的对象) return list; } /* 插入的操作 */ @Test public void test() throws SQLException { //1.获取连接对象 Connection connection = JDBCUtils.getConnection(); //2.预编译 String sql = "insert into stu(id,name) values(?,?)"; // ?:占位符 PreparedStatement ps = connection.prepareStatement(sql); //3.给占位符赋值 /* setInt(int parameterIndex, int x) parameterIndex : 占位符的索引位置 x : 赋值的数据 */ ps.setInt(1,1); ps.setString(2,"abc"); //4.执行sql //该方法可以执行增,删,改三种sql语句。返回值:有几条数据受到影响 int i = ps.executeUpdate(); System.out.println("有" + i + "条数据受到影响"); //5.关闭资源 JDBCUtils.close(connection,ps); } /* 修改的操作 */ @Test public void test2() throws SQLException { //1.获取连接对象 Connection connection = JDBCUtils.getConnection(); //2.预编译 String sql = "update stu set name=? where id=?"; PreparedStatement ps = connection.prepareStatement(sql); //3.给占位符赋值 ps.setInt(2,1); ps.setString(1,"aaa"); //4.执行sql int i = ps.executeUpdate(); System.out.println("有" + i + "条数据受到影响"); //5.关闭资源 JDBCUtils.close(connection,ps); } /* 删除数据 */ @Test public void test3() throws SQLException { //1.获取连接对象 Connection connection = JDBCUtils.getConnection(); //2.预编译 PreparedStatement ps = connection.prepareStatement("delete from stu"); //3.给占位符赋值 //4.执行sql int i = ps.executeUpdate(); System.out.println("有" + i + "条数据受到影响"); //5.关闭资源 JDBCUtils.close(connection,ps); } }
四 SQL注入
Scanner scan = new Scanner(System.in); System.out.print("用户名:"); String userName = scan.nextLine(); System.out.print("密 码:"); String password = scan.nextLine(); //SELECT id,name FROM emp WHERE id='12332' OR 1='1' AND name='123321' OR 1='1' String sql = "select id,name from emp where id = '" + userName + "' and name = '" + password + "'"; System.out.println(sql); Connection connection = JDBCUtils.getConnection(); Statement statement = connection.createStatement(); //执行sql语句 ResultSet rs = statement.executeQuery(sql); while(rs.next()){ System.out.println(rs.getString("id")); System.out.println(rs.getString("name")); } //关闭资源 rs.close(); connection.close();
五 批处理
1.注意
1.mysql驱动包的版本必须是5.1.3x 才支持批处理
2.mysql的连接:
jdbc:mysql://localhost:3306/库名?rewriteBatchedStatements=true
2.调用方法
//将数据添加到批处理中
addBatch()
//执行批处理操作
executeBatch()
//清理批处理
cleanBatch()
3.代码
//1.获取连接对象 Connection connection = JDBCUtils.getConnection(); //2.预编译 String sql = "insert into account(balance,name) values(?,?)"; PreparedStatement ps = connection.prepareStatement(sql); //3.赋值 for (int i = 1; i <= 100000 ; i++) { ps.setInt(1,i); ps.setString(2,"aa" + i); //将数据添加到批处理中 ps.addBatch(); if (i % 1000 ==0) { //4.执行sql ps.executeBatch(); //5.清空批处理 ps.clearBatch(); } } //6.关闭资源 JDBCUtils.close(connection,ps);
六 事务
1.事务的案例
aa给bb转账1000
aa -= 1000
System.out.println(1/0);
bb += 1000
注意:上面的操作可能会导致有的成功有的失败。
2.事务代码
//1.获取连接对象 Connection connection = JDBCUtils.getConnection(); try { //禁止自动提交 connection.setAutoCommit(false); //2.预编译 String sql = "update account set balance=? where name=?"; PreparedStatement ps = connection.prepareStatement(sql); //3.给占位符赋值 ps.setInt(1,1000); ps.setString(2,"aa"); //4.执行sql ps.executeUpdate(); //System.out.println(1/0); //5.给占位符赋值 ps.setInt(1,3000); ps.setString(2,"bb"); //6.执行sql ps.executeUpdate(); //事务提交 connection.commit(); }catch (Exception e){ e.printStackTrace(); //事务回滚 try { connection.rollback(); } catch (SQLException throwables) { throwables.printStackTrace(); } }finally { //允许自动提交 try { connection.setAutoCommit(true); } catch (SQLException throwables) { throwables.printStackTrace(); } }
七 连接池
1、什么是数据库连池
连接对象的缓冲区。负责申请,分配管理,释放连接的操作。
2、为什么要使用数据库连接池
通过DriverManager获取新连接,用完直接抛弃断开,连接的利用率太低,太浪费。
对于数据库服务器来说,压力太大。
3、阿里的德鲁伊连接池技术
3.1在代码中配置
//创建DruidDataSource类的对象 DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl("jdbc:mysql://localhost:3306/myemployees");//设置mysql连接的地址 dataSource.setDriverClassName("com.mysql.jdbc.Driver");//设置Driver类的全类名 dataSource.setUsername("root");//设置登录mysql的账号 dataSource.setPassword("123321");//设置登录mysql的密码 //获取连接 Connection connection = dataSource.getConnection(); System.out.println(connection);
3.2通过配置置文件进行配置
/* url=jdbc:mysql://localhost:3306/myemployees username=root password=123321 driverClassName=com.mysql.jdbc.Driver */ Properties properties = new Properties(); properties.load(this.getClass().getClassLoader(). getResourceAsStream("druid.properties")); //通过Druid工厂类创建DataSource对象 DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); //获取连接 System.out.println(dataSource.getConnection());
八 JDBCUtils
1.配置文件内容
username=root password=123321 url=jdbc:mysql://localhost:3306/myemployees?rewriteBatchedStatements=true driverClass=com.mysql.jdbc.Driver
2.代码
public class JDBCUtils { //1.获取数据库连接对象 private static String url; private static String username; private static String password; private static String driverClass; static { FileInputStream fis = null; try { //通过读取配置文件中的内容赋值 //1.创建Properites对象 Properties properties = new Properties(); //2.创建流 fis = new FileInputStream("jdbc.properties"); //3.加载流 properties.load(fis); //4.读取配置文件中的内容 url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); driverClass = properties.getProperty("driverClass"); }catch (Exception e){ e.printStackTrace(); //将编译时译常转换为运行时异常 throw new RuntimeException("XXXXXXX"); }finally { if (fis != null){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } /* 获取连接对象 */ public static Connection getConnection(){ try { Class.forName(driverClass); Connection connection = DriverManager.getConnection(url, username, password); return connection; }catch (Exception e){ e.printStackTrace(); throw new RuntimeException("获取连接失败"); } } /* 关闭资源 */ public static void close(Connection connection, PreparedStatement ps) { if (connection != null){ try { connection.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } if (ps != null){ try { ps.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } } public static void close(Connection connection, PreparedStatement ps, ResultSet resultSet) { close(connection,ps); if (resultSet != null){ try { resultSet.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } } }
九 DBUtils
/* 通过DBUtils工具类去实现增,删,改,查的功能 */ public class DBUitlsDemo { /* 查询数据 */ @Test public void test4() throws SQLException { QueryRunner qr = new QueryRunner(); /* query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) conn :连接对象 sql : sql语句 rsh :ResultSetHandler接口的实现类 BeanHandler:把结果集转为一个 Bean BeanListHandler:把结果集转为一个 Bean 的集合 params :给占位符赋值的数据 */ // Stu stu = qr.query(JDBCUtils.getConnection(), "select id,name from stu where id=?", // new BeanHandler<Stu>(Stu.class), 1); //如果JavaBean中的属性名和表中的字段名不一样可以采用别名的方式解决该问题。 List<Stu> list = qr.query(JDBCUtils.getConnection(), "select id sid,name from stu", new BeanListHandler<Stu>(Stu.class)); for (Stu s : list) { System.out.println(s); } } /* 添加 */ @Test public void test() throws SQLException { //1.创建QueryRunner的对象 QueryRunner qr = new QueryRunner(); /* update(Connection conn, String sql, Object... params) conn : 连接对象 sql : sql语句 params : 给占位符赋值的内容 */ String sql = "insert into stu(id,name) values(?,?)"; int i = qr.update(JDBCUtils.getConnection(), sql, 4, "kk"); System.out.println("有" + i + "条数据受到影响"); } /* 修改 */ @Test public void test2() throws SQLException { //1.创建QueryRunner的对象 QueryRunner qr = new QueryRunner(); String sql = "update stu set name=? where id=?"; int i = qr.update(JDBCUtils.getConnection(), sql, "jj", 4); System.out.println("有" + i + "条数据受到影响"); } /* 删除 */ @Test public void test3() throws SQLException { //1.创建QueryRunner的对象 QueryRunner qr = new QueryRunner(); String sql = "delete from stu where id=?"; int i = qr.update(JDBCUtils.getConnection(), sql, 4); System.out.println("有" + i + "条数据受到影响"); } }
十 BasicDAO
/* 对DBUtils中的方法进行二次封装 */ public class BasicDAO<T> { public List<T> query(Connection connection,String sql,Class clazz,Object...params){ try { QueryRunner qr = new QueryRunner(); List<T> list = qr.query(connection, sql, new BeanListHandler<T>(clazz),params); return list; }catch (Exception e){ throw new RuntimeException("xxxxx"); } } public void update(Connection connection,String sql,Object...params){ try { //1.创建QueryRunner的对象 QueryRunner qr = new QueryRunner(); int i = qr.update(JDBCUtils.getConnection(), sql, params); System.out.println("有" + i + "条数据受到影响"); }catch (Exception e){ throw new RuntimeException("xxxx"); } } }