JDBC连接MySQL(干货)

    技术2022-07-15  81

    JAVA连接JDBC操作数据库

    什么是JDBC

    Java DataBase Connectivity,Java数据库连接,jdbc实际是java中的一套和数据库交互的API(application program interface 应用程序编程接口)

    为什么使用JDBC

    因为Java程序员需要连接多种数据库,为了避免每一个数据库都学习一套新的API,sun公司提出了一个JDBC接口,各个数据库厂商根据此接口写实现类(驱动),这样java程序员只需要掌握JDBC接口中的一套方法,就可以访问任何数据库。 导包: import java.sql.*

    如何使用JDBC

    外网访问:https://mvnrepository.com/ 1. 从maven网站上搜索mysql 找到5.1.6版本的坐标,把坐标复制到工程的pom.xml文件中 ,在pom.xml文件源码里面project标签内部 添加<dependecies>标签,把复制的内容粘贴到里面 ,保存在工程中出现奶瓶即可、 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> 2. 创建Demo01.java 在main方法中写以下代码: //1.注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2. 获取连接对象 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/newdb3","root","root"); //System.out.println(conn); //3.创建执行SQL语句的对象 Statement stat = conn.createStatement(); //4.执行SQL String sql = "create table if not exists jdbct1(id int primary key auto_increment,name varchar(10))"; stat.execute(sql); System.out.println("执行完成"); //5.关闭资源,先打开的资源后关闭 stat.close(); conn.close();

    执行SQL的方法

    execute(sql): 此方法可以执行任意SQL,但是推荐执行DDL(create drop alter truncate) ,方法的返回值为布尔值,返回值代表是否有结果集,'true':有结果集,'false':没有结果集 executeUpdate(sql): (DML)此方法执行增删改的SQL,方法返回值为int类型,代表生效(ok)行数 executeQuery(sql): 此方法执行select查询的SQL,返回值为ResultSet结果集

    解析配置文件

    配置文件位置: src/main/resources 配置文件名:jdbc.properties driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/newdb3 username=root password=123456 initialSize=2 maxActive=10

    解析文件:

    /** * 解析Properties后缀文件,获取对应的信息 * properties后缀文件是以键值对方式存储信息 */ //创建属性对象 Properties prop= new Properties(); //得到文件输入流'Demo05表示类名' InputStream ips=Demo05.class.getClassLoader().getResourceAsStream("jdbc.properties"); //把流交给属性对象 prop.load(ips); //获取数据,只能获取到字符串类型的数据 String name = prop.getProperty("name"); String age = prop.getProperty("age"); System.out.println(name+": "+age); //注册驱动以及设置连接池 ResultSet 获取数据的方式有两种: 1、通过查询到的字段名称获取数据 rs.getString("ename"); 2、通过查询到的字段位置获取数据 rs.getString(2); 数据库类型和java类型对比: MySQL java int getInt() varchar getString() float/double getFloat()/getDouble() datetime/timestamp getDate()

    数据库连接池DBCP

    DataBase Connection Pool:数据库连接池 为什么使用:如果没有数据库连接池,每次业务都需要和数据库建立一次连接,用完之后断开,如果有1万次业务请求则有1万次连接的开和关,频繁开关连接,浪费资源,使用数据库连接池可以将连接重用,避免资源的浪费 如何使用数据库连接池 1. 下载jar包: 从maven服务器中搜索 dbcp <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> 2. 把坐标复制粘贴到pom.xml中 3. 代码如下: //创建数据源对象 BasicDataSource dataSource = new BasicDataSource(); //设置数据库连接信息 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/newdb3"); dataSource.setUsername("root"); dataSource.setPassword("123456"); //设置初始连接数量 dataSource.setInitialSize(3); //设置最大连接数量 dataSource.setMaxActive(5); //从连接池中得到连接 Connection conn = dataSource.getConnection(); System.out.println(conn);

    @Test 测试单元注解 只能对无参无返回值的方法进行单元测试

    SQL的注入风险
    select count(*) from t_user where username='libai' and password='admin1'; SQL注入的演示 执行语句 String sql = "insert into jdbcuser values(null,'"+name+"',"+age+")"; 输入:' or '1'='1 输出SQL拼接语句: select count(*) from t_user where username='asdfsdf' and password='' or '1'='1' 出现登陆成功状态
    PreparedStatement对象
    预编译的SQL对象 1. 为什么PreparedStatement可以避免SQL注入? 因为预编译的SQL执行对象 在创建stat对象的时候已经将SQL进行编译并且把SQL语句的逻辑固定,不会因为后期替换进去的内容改变SQL语句 String sql = "select count(*) from t_user where username=? and password=?"; stat = conn.prepareStatement(sql); //替换问号的值 stat.setString(1, username); stat.setString(2, password); //执行SQL rs = stat.executeQuery(); '不需要传入参数' 2、好处 1. 代码更直观避免了拼接SQL语句 2. 可以避免SQL注入 3. 执行效率略高于statement 如果SQL语句中存在变量则使用PreparedStatement,如果没有变量则使用Statement

    批量操作

    将多次和数据库服务器的数据交互合并成一次,提高执行效率 '添加到批量操作中' stat.addBatch(sql1); stat.addBatch(sql2); stat.addBatch(sql3); '执行批量操作' stat.executeBatch();

    事务

    1、设置自动提交的状态 conn.setAutoCommit(false/true); 2、提交 conn.commit(); 3、回滚 conn.rollback(); 案例:实现超人有5000 蝙蝠侠100 让超人给蝙蝠侠转账2000,程序第一次运行转账成功 第二次转账成功第三次转账失败 create table person(id int primary key auto_increment,name varchar(10), money int); insert into person values(null,'超人',5000),(null,'蝙蝠侠',100); 获取自增主键的值 Statement stat.executeUpdate(sql,Statement.RETURN_GENERATED_KEYS); PreparedStatement stat = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS); 获取主键值 rs =stat.getGeneratedKeys(); while(rs.next()){ //得到返回的主键值 int key=rs.getInt(1); System.out.println("自动生成的ID:"+key); }

    获取元数据

    元数据包括:数据库的元数据和表的元数据 1. 数据库元数据里面保存一些和数据库相关的信息 如:数据库厂商名称,数据库驱动版本,数据库连接地址,用户名等等 //得到数据库的元数据 DatabaseMetaData dbmd = conn.getMetaData(); System.out.println("驱动版本:"+dbmd.getDriverVersion()); System.out.println("连接地址:"+dbmd.getURL()); System.out.println("用户名:"+dbmd.getUserName()); System.out.println("数据库厂商:"+dbmd.getDatabaseProductName()); 2. 表的元数据里面保存一些和表相关的信息 如:表有多少字段,每个字段的名称、类型等 //从结果集中得到表的元数据 ResultSetMetaData rsmd = rs.getMetaData(); //得到表字段的数量 int count = rsmd.getColumnCount(); //得到每个字段的字段名和类型 for (int i = 0; i < count; i++) { String name = rsmd.getColumnName(i+1); String type = rsmd.getColumnTypeName(i+1); System.out.println(name+":"+type); }

    JDBC练习源代码

    JAV中连接JDBC需要导包: import java.sql.***; '必须导入java.sql.下面的包,否则会出错' 1、注册驱动 Class.forName("com.mysql.jdbc.Driver"); 2、获取连接对象 Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/newdb3","root", "123456"); 3、创建执行SQL语句对象 Statement stat=conn.createStatement(); 4、执行SQL String sql = "create table if not exists jdbct1(id int primary key auto_increment,name varchar(10))"; stat.execute(sql); //查询表中的数据,见到ResultSet就是用while循环 String sql="select * from emp"; rs=stat.executeQuery(sql); while(rs.next()){ int id=rs.getInt("empno"); String name=rs.getString("ename"); int sal=rs.getInt("sal"); System.out.println("ID:"+id+" 姓名:"+name+" 工资:"+sal); } 5、关闭资源 stat.close(); conn.close(); 6、解析jdbc.properties配置文件'文件路径src/main/resources' 解析Properties后缀文件,获取对应的信息,properties后缀文件是以键值对方式存储信息 例如: driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/newdb3 username=root password=123456 //创建属性对象 Properties prop= new Properties(); //得到文件输入流,Demo05当前类名 InputStream ips=Demo05.class.getClassLoader().getResourceAsStream("jdbc.properties"); //把流交给属性对象 prop.load(ips); //获取数据,只能获取到字符串类型的数据 String username = prop.getProperty("username"); String password = prop.getProperty("password"); System.out.println(username+": "+password); 7、创建数据库连接池 //创建数据源对象 BasicDataSource dataSource= new BasicDataSource(); //设置数据库连接信息 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/newdb3"); dataSource.setUsername("root"); dataSource.setPassword("123456"); //设置初始连接数量 dataSource.setInitialSize(3); //设置最大连接数量 dataSource.setMaxActive(5); //从连接池中得到连接 Connection conn= dataSource.getConnection(); System.out.println(conn); 8、解析配置文件与连接池配合使用 private static BasicDataSource dataSource; static{ //创建属性对象 Properties prop= new Properties(); //得到文件输入流 InputStream ips=Demo05.class.getClassLoader().getResourceAsStream("jdbc.properties"); //把流交给属性对象 try { prop.load(ips); //获取数据,只能获取到字符串类型的数据 String driver = prop.getProperty("driver"); String url = prop.getProperty("url"); String username = prop.getProperty("username"); String password = prop.getProperty("password"); /**创建数据库连接池*/ //创建数据源对象 dataSource= new BasicDataSource(); //设置数据库连接信息 dataSource.setDriverClassName(driver); dataSource.setUrl(url); dataSource.setUsername(username); dataSource.setPassword(password); //设置初始连接数量 dataSource.setInitialSize(3); //设置最大连接数量 dataSource.setMaxActive(5); } catch (IOException e) { e.printStackTrace(); } } //从连接池中得到连接 public static Connection getConn() throws SQLException{ return dataSource.getConnection(); } //关闭打开的资源 public static void close(Connection conn,Statement stat,ResultSet rs){ try { if(rs!=null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if(stat!=null){ stat.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if(conn!=null){ //保证自动提交处于打开状态,必要时会在程序中关闭自动提交 conn.setAutoCommit(true); conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } 9、连接池做测试 public class demo02 { public static void main(String[] args) throws SQLException { threadTest t1=new threadTest(); t1.start(); threadTest t2=new threadTest(); t2.start(); threadTest t3=new threadTest(); t3.start(); threadTest t4=new threadTest(); t4.start(); threadTest t5=new threadTest(); t5.start(); } } class threadTest extends Thread{ @Override public void run(){ //获取连接 try { Connection conn = DBUtils.getConn(); System.out.println("获取连接!"); //模拟耗时 Thread.sleep(5000); //归还连接 conn.close(); System.out.println("归还连接!"); } catch (SQLException e) { e.printStackTrace(); } catch(Exception e){ e.printStackTrace(); } } } 10、PreparedStatement使用测试 public static void main(String[] args) { Scanner scan=new Scanner(System.in); System.out.println("请输入用户名:"); String name = scan.nextLine(); System.out.println("请输入年龄:"); int age = Integer.parseInt(scan.nextLine()); Connection conn = null; //预编译的SQL执行对象 PreparedStatement stat = null; ResultSet rs = null; try { conn = DBUtils.getConn(); String sql = "insert into jdbcuser values(null,?,?)"; stat = conn.prepareStatement(sql); //把? 替换成真正的数据 stat.setString(1, name); stat.setInt(2, age); //执行SQL语句 stat.executeUpdate(); System.out.println("插入数据成功!"); } catch (Exception e) { e.printStackTrace(); } finally { DBUtils.closeSource(conn, stat, rs); } } 11、批量插入练习 public static void main(String[] args) { Connection conn = null; Statement stat = null; ResultSet rs = null; try { conn = DBUtils.getConn(); stat = conn.createStatement(); String sql1="insert into jdbcuser values(null,'张三',20)"; String sql2="insert into jdbcuser values(null,'李四',21)"; String sql3="insert into jdbcuser values(null,'王五',22)"; //stat.executeUpdate(sql1); //stat.executeUpdate(sql2); //stat.executeUpdate(sql3); //添加到批量操作中 stat.addBatch(sql1); stat.addBatch(sql2); stat.addBatch(sql3); //执行批量操作 stat.executeBatch(); System.out.println("插入数据成功!"); } catch (Exception e) { e.printStackTrace(); } finally { DBUtils.closeSource(conn, stat, rs); } } public static void main(String[] args) { Connection conn = null; PreparedStatement stat = null; ResultSet rs = null; try { long time0 = System.currentTimeMillis(); conn = DBUtils.getConn(); String sql = "insert into jdbcuser values(null,?,?)"; stat = conn.prepareStatement(sql); for(int i=1;i<=100;i++){ stat.setString(1,"name"+i); //替换 ? stat.setInt(2, 100+i); //添加到批量操作 stat.addBatch(); //每20条执行一次 if(i%20==0){ //执行批量操作 stat.executeBatch(); //清除批量操作 stat.clearBatch(); } } stat.executeBatch(); long time1 = System.currentTimeMillis(); System.out.println("插入数据成功!耗时:"+(time1 - time0)+"ms"); } catch (Exception e) { e.printStackTrace(); } finally { DBUtils.closeSource(conn, stat, rs); } } 12、分页查询 public static void main(String[] args) { Scanner scan=new Scanner(System.in); System.out.println("请输入查询页数:"); int page= Integer.parseInt(scan.nextLine()); if(page<=0){ //查询页数不可以为负数 page=1; } System.out.println("请输入查询条数:"); int num = Integer.parseInt(scan.nextLine()); Connection conn = null; PreparedStatement stat = null; ResultSet rs = null; try { conn = DBUtils.getConn(); String sql = "select * from jdbcuser limit ?,?"; stat = conn.prepareStatement(sql); stat.setInt(1,(page-1)*num); stat.setInt(2, num); rs=stat.executeQuery(); while(rs.next()){ int id=rs.getInt("id"); String name = rs.getString("name"); System.out.println("ID:"+id+" name:"+name); } System.out.println("插入数据成功!"); } catch (Exception e) { e.printStackTrace(); } finally { DBUtils.closeSource(conn, stat, rs); } } 13、转账练习 public static void main(String[] args) { Connection conn = null; Statement stat = null; ResultSet rs = null; try { conn = DBUtils.getConn(); conn.setAutoCommit(false); stat =conn.createStatement(); String sql1 = "update person set money=money-2000 where id=1"; String sql2 = "update person set money=money+2000 where id=2"; stat.executeUpdate(sql1); stat.executeUpdate(sql2); //得到超人剩余的钱数,如果大于等于0,则允许转账,否则回滚 rs=stat.executeQuery("select money from person where id=1"); while(rs.next()){ int money = rs.getInt("money"); if(money>=0){ System.out.println("转账成功!"); conn.commit(); //提交 } else{ System.out.println("转账失败!"); conn.rollback(); //回滚 } } System.out.println("操作成功!"); } catch (Exception e) { e.printStackTrace(); } finally { DBUtils.closeSource(conn, stat, rs); } } 13、向表中插入数据,队名并且获取主键,根据主键插入队员,实现关系表 public static void main(String[] args) { //createTable(); Scanner scan=new Scanner(System.in); System.out.println("请输入球队名称:"); String teamName = scan.nextLine(); System.out.println("请输入球员名称:"); String playName = scan.nextLine(); scan.close(); Connection conn = null; PreparedStatement stat = null; ResultSet rs = null; try { conn = DBUtils.getConn(); /** * 查询是否存在用户输入的球队 */ String sql = "select * from team where name=?"; stat = conn.prepareStatement(sql); stat.setString(1, teamName); rs = stat.executeQuery(); int tid =-1; while(rs.next()){ //得到已经保存的球队id tid = rs.getInt("id"); } //判断是否保存过球队 if(tid==-1){ sql = "insert into team values(null,?)"; stat.close(); //获取主键值 stat = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS); stat.setString(1, teamName); stat.executeUpdate(); rs.close(); //得到主键值 rs = stat.getGeneratedKeys(); while(rs.next()){ tid = rs.getInt(1); System.out.println("teamId="+tid); } } //插入球员 sql = "insert into player values(null,?,?)"; stat.close(); stat = conn.prepareStatement(sql); stat.setString(1, playName); stat.setInt(2, tid); //执行 stat.executeUpdate(); System.out.println("操作成功!"); } catch (Exception e) { e.printStackTrace(); } finally { DBUtils.closeSource(conn, stat, rs); } } 14、获取元数据 public static void main(String[] args) { Connection conn = null; Statement stat = null; ResultSet rs = null; try { conn = DBUtils.getConn(); //得到数据库的元数据 DatabaseMetaData dbmd=conn.getMetaData(); System.out.println("驱动版本:"+dbmd.getDriverMajorVersion()); System.out.println("链接地址:"+dbmd.getURL()); System.out.println("用户名:"+dbmd.getUserName()); System.out.println("数据库厂商:"+dbmd.getDatabaseProductName()); stat=conn.createStatement(); rs = stat.executeQuery("select * from emp"); //从结果集体中得到表的元数据 ResultSetMetaData rsmd=rs.getMetaData(); int count = rsmd.getColumnCount(); //得到表字段的数量 System.out.println("表字段数量:"+count); //得到每个字段的字段名和类型 for(int i=0;i<count;i++){ String name = rsmd.getColumnName(i+1).toLowerCase(); String type= rsmd.getColumnTypeName(i+1).toLowerCase(); System.out.println(name+" "+type); } System.out.println("操作成功!"); } catch (Exception e) { e.printStackTrace(); } finally { DBUtils.closeSource(conn, stat, rs); } }
    Processed: 0.009, SQL: 9