Java学习总结(十九)——JDBC操作数据库,预编译的使用,事务,常见的连接池
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java学习总结(十九)——JDBC操作数据库,预编译的使用,事务,常见的连接池相关的知识,希望对你有一定的参考价值。
一.JDBC操作数据库
1. JDBC(Java DataBase Connection,java数据库连接),由一些接口和类构成的API。
图示:
2. JDBC操作数据库的步骤:
(1)注册驱动
(2)建立连接(Connectoin)
(3)创建执行SQL的语句(Statement)
(4)执行SQL语句(通过Statement或PreparedStatement)
(5)处理执行结果(resultSet)
(6)释放资源
3. 建立连接:
(1)Connection conn=DriverManager.getConnection(url,user,password);
(2)Url格式:Jdbc:子协议://主机名:端口/数据库名? 属性名=属性值&......
(3)User(用户名),password(密码)可以用,“属性名=属性值”方式告诉数据库
(4)其他参数如:
useUnicode=true&characterEncoding=GBK。
4. 执行sql时:
(1)增,删,改用executeUpdate()方法
(2)查询时使用executeQuery()方法
例1(向数据库中添加元素):
(1)创建工程,引入数据库连接jar包,并建立环境连接;
(2)编写代码(往):
package org.jdbc.insert; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class InsertDemo { public static void main(String[] args) { Connection conn = null; Statement stat = null; try { // 1.建立驱动,加载驱动程序 Class.forName("com.mysql.jdbc.Driver"); // 2.建立连接,与数据库进行连接 conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/mydb?characterEncoding=utf8", "root", "qitao1996"); // 3.编写待执行的sql语句,以及sql语句执行对象 String sql = "insert into students(id,name,age,score) values(15,'丁明君',22,93.2),(16,'小昭',18,94.7)"; stat = conn.createStatement(); // 4.执行sql语句,并返回影响数据库表中的行数 int count = stat.executeUpdate(sql); // 5.处理运行结果 if (count > 0) { System.out.println("数据添加成功,影响了表中" + count + "行数据!!!!!"); } } catch (Exception e) { e.printStackTrace(); } finally { try { // 6.释放资源 conn.close(); stat.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
|
(3)运行结果:
例2(查询数据库中元素,并打印到控制台):
(1)编写代码:
package org.jdbc.select; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class QueryDemo { public static void main(String[] args) { Connection conn=null; Statement stat=null; ResultSet rs=null; try { Class.forName("com.mysql.jdbc.Driver");//建立驱动 //建立连接 conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?user=root&password=qitao1996"); String sql="select * from students";//编写sql语句 stat=conn.createStatement();//创建执行 rs= stat.executeQuery(sql);//执行sql语句,并返回查询到的结果集 System.out.println("获取到的学生信息为:"); System.out.println("学号 姓名 年龄 成绩"); //遍厉获取查询到的结果集 while(rs.next()){ int id=rs.getInt("id"); String name=rs.getString("name"); int age=rs.getInt("age"); double score=rs.getDouble("score"); System.out.println(id+" "+name+" "+age+" "+score); } } catch (Exception e) { e.printStackTrace(); }finally{ try { conn.close(); stat.close(); rs.close();//释放资源 } catch (SQLException e) { e.printStackTrace(); } } } }
|
(2)运行结果:
5. 批处理:
(1)应用addBatch()方法添加批处理语句
(2)使用executeBatch方法执行批处理
例3(分别编写增,删,改语句各一条一次执行):
(1)编写代码:
package org.jdbc.batch; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class BatchDemo { public static void main(String[] args) { Connection conn=null; Statement stat=null; try { Class.forName("com.mysql.jdbc.Driver");//建立驱动 //建立连接 conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","qitao1996"); stat=conn.createStatement(); //下面添加批处理语句 stat.addBatch("insert into students(id,name,age,score) values(12,'荆轲',20,97.2 )"); stat.addBatch("delete from students where id=7"); stat.addBatch("update students set id=10 where id=9"); int[] array=stat.executeBatch();//执行批处理命令 int i=1; for(int count:array){ System.out.println("第"+i+"条语句执行影响行数为"+count); i++; } } catch (Exception e) { e.printStackTrace(); }finally{ try { conn.close(); stat.close(); } catch (SQLException e) { e.printStackTrace(); } } } } |
(2)运行结果:
二.PreparedStatement的使用
1. preparedStatement是Statement的子接口,属于预处理操作
2. 获取PreparedStatement的方法:
使用Connection对象的PreparedStatement preparedstatement(String sql)
3. 使用PreparedStatement的好处:
(1)对于相同结构的SQL,可以提高执行效率:
@@1.在创建PreparedStatement对象时就指定了sql语句,该语句将立即被发送给DBMS进行编译
@@2.预编译的语句被存储在DBMS的缓存中,下次执行相同的SQL语句时,则可以从缓存中取出来。
(2)可以有效地预防SQL注入:
在使用参数化查询的情况下,数据库系统(DBMS)不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,即使参数中含有恶意的指令,也不会被数据库所运行
根据以前所学,我们先来编写一个获取JDBC连接的对象的工具类方便后续代码使用:
(1)首先在src目录下新建一个properties属性文件
内容:
driverclass=com.mysql.jdbc.Driver user=root password=qitao1996 url=jdbc:mysql://127.0.0.1:3306/boke18 |
(2)编写工具类代码
package org.jdbc.util; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; //操作数据库的工具类 public class DBUtil { // 私有化构造方法 private DBUtil() { } private static String url = null; private static String user = null; private static String password = null; static { try { Class.forName("com.mysql.jdbc.Driver"); Properties pro = new Properties(); pro.load(new FileInputStream("src/jdbc.properties")); url = pro.getProperty("url"); user = pro.getProperty("user"); password = pro.getProperty("password"); } catch (Exception e) { e.printStackTrace(); } } // 读取外部属性文件获取连接对象,需手动输入url public static Connection getConnection1(String url) { Properties pro = new Properties(); Connection conn = null; InputStream input = null; try { input = new FileInputStream("E:" + File.separator + "JDBC.properties"); pro.load(input); conn = DriverManager.getConnection(url, pro); } catch (Exception e) { e.printStackTrace(); } return conn; } // 读取工程下的配置文件,获取连接对象参数,不需手动输入url public static Connection getConnection2() throws SQLException { Connection conn = DriverManager.getConnection(url, user, password); return conn; } // 释放全部资源 public static void closeAll(Connection conn, Statement stat, ResultSet rs) throws SQLException { if (conn != null) { conn.close(); } if (stat != null) { stat.close(); } if (rs != null) { rs.close(); } } // 释放所用资源 public static void closePart(Connection conn, Statement stat) throws SQLException { if (conn != null) { conn.close(); } if (stat != null) { stat.close(); } } }
|
例1(根据拼串来模拟SQL注入):
(1)利用上述工具类编写代码:
package org.jdbc.inject; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.jdbc.util.DBUtil; public class SqlInjectDemo { public static void main(String[] args) { Statement stat=null; ResultSet rs=null; Connection conn=null; try { conn=DBUtil.getConnection2(); stat=conn.createStatement(); String username="西施"; String password="xyz' or '1=1"; String sql="select * from user where username='"+username+"' and password='"+password+"'"; System.out.println(sql); rs=stat.executeQuery(sql); if(rs.next()){ System.out.println("恭喜你登录,成功"); }else{ System.out.println("很遗憾,你的用户名或密码输入错误,登录失败"); } } catch (Exception e) { e.printStackTrace(); }finally{ try { DBUtil.closeAll(conn, stat, rs); } catch (SQLException e) { e.printStackTrace(); } } } }
|
(2)运行结果:
我们来查询user表中元素,看看是否出现了sql注入现象
对比可以知道,在这个例子中就出现了SQL注入,导致我们程序的不安全性
例2(现在我们来使用预编译的方法防止SQL的注入):
(1)编写代码:
package org.jdbc.inject; import java.io.BufferedReader; import java.io.InputStreamReader; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.jdbc.util.DBUtil; public class StopInject { public static void main(String[] args) { PreparedStatement ps = null; ResultSet rs = null; Connection conn = null; String sql = "select * from user where username=? and password=? ";// 编写预编译sql BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); try { conn = DBUtil.getConnection2(); ps = conn.prepareStatement(sql); System.out.print("请输入用户名:"); String username = br.readLine(); System.out.print("请输入密码:"); String password = br.readLine(); ps.setString(1, username); ps.setString(2, password); rs = ps.executeQuery();// 执行sql语句 if (rs.next()) { System.out.println("恭喜你,登录成功...."); } else { System.out.println("你的用户名或密码输入错误,登录失败...."); } } catch (Exception e) { e.printStackTrace(); } finally { try { DBUtil.closeAll(conn, ps, rs); } catch (SQLException e) { e.printStackTrace(); } } } } |
(2)运行结果:
当用户名密码都正确时:
利用拼串,鼓故意写错密码时:
由此我们清楚地发现预编译有效地防止了SQL注入现象
例3(使用预编译向表中添加和查询元素):
(1)编写代码:
package org.jdbc.inject; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.jdbc.bean.User; import org.jdbc.util.DBUtil; public class InsertDemo { // 获取类中可以共用的对象 private static Connection conn = null; private static PreparedStatement ps = null; private static ResultSet rs = null; // 代码运行时即开始连接数据库 static { try { conn = DBUtil.getConnection2(); } catch (SQLException e) { e.printStackTrace(); } } // 添加元素 public static void main(String[] args) { String sql = "insert into user(username,password) values(?,?)"; try { // 将SQL发送到DBMS中,进行预编译,将预编译好的SQL存储于DBMS的缓冲区中 ps = conn.prepareStatement(sql); for (int i = 1; i <= 5; i++) { ps.setString(1, "貂蝉" + i); ps.setString(2, "64262" + i); ps.executeUpdate(); } System.out.println("数据库中批量添加元素成功..."); System.out.println("查看表中元素"); userInsert();// 调用对象添加方法 selectAll();// 调用查询方法 } catch (SQLException e) { e.printStackTrace(); } finally { try { DBUtil.closePart(conn, ps);// 释放资源 } catch (SQLException e) { e.printStackTrace(); } } } // 查询元素 public static void selectAll() { List<User> list = new ArrayList<User>(); String sql = "select * from user"; try { ps = conn.prepareStatement(sql); rs = ps.executeQuery();// 执行sql System.out.println("查询user表得:"); System.out.println("编号 用户名 密码"); // 遍厉打印元素 User user = new User(); while (rs.next()) { int id = rs.getInt("id"); String username = rs.getString("username"); String password = rs.getString("password"); System.out.println(id + " " + username + " " + password); user = new User(id, username, password); list.add(user);// 将对象添加到集合中 } for (User user1 : list) { System.out.println(user1); } } catch (SQLException e) { e.printStackTrace(); } finally { try { DBUtil.closeAll(conn, ps, rs); } catch (SQLException e) { e.printStackTrace(); } } } }
|
(2)运行结果:
例4(我们将查询到的数据封装到JavaBean中):
(1)首先编写JavaBean,用来封装数据
package org.jdbc.bean; public class User { private int id; private String username; private String password; public User(){ } public User(String username, String password) { this.username = username; this.password = password; } public User(int id, String username, String password) { this.id = id; this.username = username; this.password = password; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", password=" + password + "]"; } }
|
(2)我们将例3中查询方法稍作修改,将元素封装到List集合中:
List<User> list = new ArrayList<User>(); String sql = "select * from user"; try { ps = conn.prepareStatement(sql); rs = ps.executeQuery();// 执行sql System.out.println("查询user表得:"); System.out.println("编号 用户名 密码"); // 遍厉打印元素 User user = new User(); while (rs.next()) { int id = rs.getInt("id"); String username = rs.getString("username"); String password = rs.getString("password"); System.out.println(id + " " + username + " " + password); user = new User(id, username, password); list.add(user);// 将对象添加到集合中 } for (User user1 : list) { System.out.println(user1); }
(3)运行结果:
例5(将Java中的对象添加到数据库中去):
(1)编写代码(以上述代码为基础,添加一个添加对象的方法):
// 将JavaBean中的对象添加到数据库中 public static void userInsert() { List<User> list = new ArrayList<User>(); User user = new User(); for (int j = 1; j <= 5; j++) { user = new User("武则天" + j, "75332" + j); list.add(user); } String sql = "insert into user(username,password) values(?,?)"; int count = 0; try { ps = conn.prepareStatement(sql); for (User user2 : list) { ps.setString(1, user2.getUsername()); ps.setString(2, user2.getPassword()); count = ps.executeUpdate(); } if (count > 0) { System.out.println("添加元素成功.."); } else { System.out.println("添加元素失败.."); } } catch (SQLException e) { e.printStackTrace(); } // 查询完毕后,由查询方法释放资源 } |
(2)运行结果:
三.事务
1. 概念:数据库事务(Database Transaction),是指作为单个逻辑工作单元执行的那一系列操作,要么全部成功,要么全部失败
2. 事务的四个特性:
(1)原子性:原子性是指事务是一个不可分割的单位,事务中的操作要么都发生,要么都失败
(2)一致性:事务必须使数据库从一个一致性的状态变换到另一个一致性的状态
(3)隔离性:事务的隔离级别是指一个事务的执行不被其他事务所干扰,即一个事务内部的操作及使用的数据对并发的 其他事务是隔离的,并发执行的各个事务之间不能互相干扰
(4)持久性:持久性是指一个事务一旦被提交,它对数据库中的数据改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何的影响
3. 事务的隔离级别
前提概念:
(1)脏读(dirty read):一个事务读取到了另一个事务未提交的数据(脏数据)的现象
(2)不可重复读:一个事务两次读取到的数据不一致的现象
(3)幻读:一个事务在读取数据时,另一个事务添加了数据记录,则第一个事务读取到了新添加的数据(与第一次读取到的数据比较)
级别分类:
(1)读未提交级别(read uncommitted):读取到了另一个事务还未提交的数据,可能发生脏读,不可重复读,幻读。
(2)读提交级别(read committed):只能读取其他事务已经提交的数据,可能会发生不可重复读,幻读
(3)可重复提交级别(repeatable read,MySQL默认隔离级别):在一个事务中可以重复读取相同的数据在InnoDB数据库存储引擎(此存储引擎支持事务)中,已经解决了幻读问题。
(4)串行化级别(serialzable): 最安全,但并发效率低。
4. 隔离级别多线程并发读取数据时的正确性
隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交(Read uncommitted) | V | V | V |
读已提交(Read committed) | x | V | V |
可重复读(Repeatable read) | x | x | V |
可串行化(Serializable ) | x | x | x |
V:可能出现,X:不会出现
5. Java对事务的支持
(1)当一个连接对象被创建时,默认情况下是自动提交事务:每次执行一个 SQL 语句时,如 果执行成功,就会向数据库自动提交,而不能回滚
为了让多个 SQL 语句作为一个事务执行:
(2)调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务
(3)在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
(4)在出现异常时,调用 rollback(); 方法回滚事务
(5)若此时 Connection 没有被关闭, 则需要恢复其自动提交状态
例1(模拟银行账户对事物进行深入理解,具有转账,查询功能):
(1)编写代码:
package org.jdbc.transcation; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Scanner; import org.jdbc.util.DBUtil; public class AccountDemo { // 主方法控制运行方向 public static void main(String[] args) { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); Scanner scan = new Scanner(System.in); while (true) { System.out.print("请输入你的选择(1 转账 2 查询 3退出):"); int chioce; try { chioce = scan.nextInt(); switch (chioce) { case 1: System.out.print("请输入转出账户的姓名:"); String fromName = br.readLine(); System.out.print("请输入转入账户姓名:"); String toName = br.readLine(); System.out.print("请输入转账金额:"); int money = scan.nextInt(); boolean flag = transFerMoney(fromName, toName, money); if (flag) { System.out.println("转账成功"); } else { System.out.println("sorry,ATM发生故障,转账失败!"); } break; case 2: System.out.print("请选择 (1:查询全部账户 2:个人账户):"); int chioce1 = scan.nextInt(); switch (chioce1) { case 1: selectAll(); break; case 2: System.out.print("请输入查询账户姓名:"); String balName = br.readLine(); selectPart(balName); break; } break; case 3: System.out.println("谢谢你的光临,再见!!"); System.exit(0); } } catch (IOException e) { e.printStackTrace(); } } } // 转钱方法 public static boolean transFerMoney(String fromName, String toName, int money) { boolean flag = false; PreparedStatement ps = null; Connection conn = null; try { conn = DBUtil.getConnection2(); conn.setAutoCommit(false);// 取消自动提交 String sql1 = "update account set balance=balance-? where name=?"; String sql2 = "update account set balance=balance+? where name=?"; ps = conn.prepareStatement(sql1); ps.setInt(1, money); ps.setString(2, fromName);// 转出 ps.executeUpdate(); ps.close(); ps = conn.prepareStatement(sql2); ps.setInt(1, money); ps.setString(2, toName);// 转入 ps.executeUpdate(); conn.commit();// 提交事务 flag = true; } catch (SQLException e) { e.printStackTrace(); } finally { try { DBUtil.closePart(conn, ps); } catch (SQLException e) { e.printStackTrace(); } } return flag; } // 全部账户查询方法 public static void selectAll() { PreparedStatement ps = null; Connection conn = null; ResultSet rs = null; try { conn = DBUtil.getConnection2();// 建立连接 String sql = "select * from account"; ps = conn.prepareStatement(sql); rs = ps.executeQuery(); System.out.println("全部账户查询结果为:"); System.out.println("编号 姓名 账户余额"); while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); int balance = rs.getInt("balance"); System.out.println(id + " " + name + " " + balance); } } catch (SQLException e) { e.printStackTrace(); } finally { try { DBUtil.closeAll(conn, ps, rs); } catch (SQLException e) { e.printStackTrace(); } } } // 查询单人账户 public static void selectPart(String balName) { PreparedStatement ps = null; Connection conn = null; ResultSet rs = null; try { conn = DBUtil.getConnection2();// 建立连接 String sql3 = "select * from account where name=?"; ps = conn.prepareStatement(sql3); ps.setString(1, balName); rs = ps.executeQuery(); System.out.println(balName + "账户查询结果为:"); System.out.println("编号 姓名 账户余额"); while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); int balance = rs.getInt("balance"); System.out.println(id + " " + name + " " + balance); } } catch (SQLException e) { e.printStackTrace(); } finally { try { DBUtil.closeAll(conn, ps, rs); } catch (SQLException e) { e.printStackTrace(); } } } }
|
(2)运行结果:
请输入你的选择(1 转账 2 查询 3退出):2 请选择 (1:查询全部账户 2:个人账户):1 全部账户查询结果为: 编号 姓名 账户余额 1 项羽 35000000 2 刘邦 20000000 3 李世民 50000000 4 赵匡胤 24000000 请输入你的选择(1 转账 2 查询 3退出):1 请输入转出账户姓名:项羽 请输入转入账户姓名:刘邦 请输入转账金额:3000 转账成功 请输入你的选择(1 转账 2 查询 3退出):2 请选择 (1:查询全部账户 2:个人账户):2 请输入查询账户姓名:刘邦 刘邦账户查询结果为: 编号 姓名 账户余额 2 刘邦 20003000 请输入你的选择(1 转账 2 查询 3退出):1 请输入转出账户姓名:项羽 请输入转入账户姓名:李世民 请输入转账金额:3000 转账成功 请输入你的选择(1 转账 2 查询 3退出):2 请选择 (1:查询全部账户 2:个人账户):1 全部账户查询结果为: 编号 姓名 账户余额 1 项羽 34994000 2 刘邦 20003000 3 李世民 50003000 4 赵匡胤 24000000 请输入你的选择(1 转账 2 查询 3退出):3 谢谢你的光临,再见!!
|
四.常见的数据库连接池
1.连接池:存储,并高效管理数据库连接对象的容器连接池,一般用于短暂的频繁的去建立链接,去操作数据库,比较节省资源,我们根据数据库建立一次链接,底层来说还是比较耗费资源的
2.DBCP的使用:
(1)导入DBCP的两个jar包,以及数据库驱动jar包;
(2)编码:
方式一(硬编码):
package org.jdbc.dbcpdemo; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import org.apache.commons.dbcp.BasicDataSource; public class DBCPDemo1 { public static void main(String[] args) throws SQLException { BasicDataSource ds = new BasicDataSource(); // 1.设置参数 ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/boke18"); ds.setUsername("root"); ds.setPassword("qitao1996"); // 2.获取连接对象 Connection conn = ds.getConnection(); String sql = "insert into user(username,password) values(?,?)"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, "平昭阳公主"); ps.setString(2, "987654"); int count = 0; count = ps.executeUpdate(); if (count != 0) { System.out.println("添加成功.."); } else { System.out.println("添加失败.."); } conn.close(); ps.close(); } }
|
运行结果:
方式二(配置文件的方式):
加入配置文件:dbcp.properties
代码:
package org.jdbc.dbcpdemo; import java.io.FileInputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; public class DBCPDemo2 { public static void main(String[] args) throws Exception { //用属性集合读取属性文件 Properties pro=new Properties(); pro.load(new FileInputStream("src/dbcp.properties")); //传入属性集合 @SuppressWarnings("static-access") DataSource ds=new BasicDataSourceFactory().createDataSource(pro); Connection conn=ds.getConnection(); String sql = "insert into user(username,password) values(?,?)"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, "窦漪房"); ps.setString(2, "789654"); int count = 0; count = ps.executeUpdate(); if (count != 0) { System.out.println("添加成功.."); } else { System.out.println("添加失败.."); } conn.close(); ps.close(); } }
|
运行结果:
3.c3p0的使用:
(1)导入jar包
编码方式一(硬编码):
核心代码:
ComboPooledDataSource ds = new ComboPooledDataSource(); //设置参数 ds.setDriverClass("com.mysql.jdbc.Driver"); ds.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/mydb"); ds.setUser("root"); ds.setPassword("123456"); //获取链接对象 Connection conn = ds.getConnection(); String sql = "insert into users values(?,?)"; PreparedStatement statement = conn.prepareStatement(sql); statement.setString(1, "找六2"); statement.setString(2, "654321"); statement.executeUpdate(); conn.close(); ds.close(); |
编码方式二(读取配置文件):
package org.jdbc.c3p0demo; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Demo { public static void main(String[] args) throws SQLException { ComboPooledDataSource ds=new ComboPooledDataSource("myoracle"); Connection conn=ds.getConnection(); String sql = "insert into user(username,password) values(?,?)"; PreparedStatement ps=conn.prepareStatement(sql); ps.setString(1, "梁红玉"); ps.setString(2, "678954"); int count=0; count= ps.executeUpdate(); if(count!=0){ System.out.println("添加成功.."); }else{ System.out.println("添加失败.."); } ps.close(); conn.close(); } }
|
运行结果:
4. DButils的使用:
(1)代码:
package org.jdbc.dbutils; import java.sql.SQLException; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.jdbc.bean.User; import com.mchange.v2.c3p0.ComboPooledDataSource; public class DButilsDemo { public static void main(String[] args) throws SQLException { // dbutils 封装了操作对象 配合C3P0一起使用 ComboPooledDataSource ds = new ComboPooledDataSource(); QueryRunner runner = new QueryRunner(ds); // runner.update() 执行增删改 // runner.query() 执行查询语句 String sql = "insert into user(name,password) values('小周后','abcdefef')"; sql= "insert into user(name,password) values(?,?)"; sql = "select * from user"; // runner.update(sql); 执行增删改 // runner.update(sql,100,"ggggg"); // 执行查询语句,查询出来的数据,封装好返回 List<User> querys = runner.query(sql, new BeanListHandler<User>( User.class)); System.out.println(querys); ds.close(); } }
|
(2)运行结果:
【本次总结完毕】
以上是关于Java学习总结(十九)——JDBC操作数据库,预编译的使用,事务,常见的连接池的主要内容,如果未能解决你的问题,请参考以下文章