一、JDBC简介
1.JDBC是什么?2.JDBC编写步骤 二、如何获取数据库连接
1.获取数据库连接方法一2.获取数据库连接方法二3.获取数据库连接方法三4.获取数据库连接方法四5.获取数据库连接方法五(推荐) 三、JDBC基本 *** 作
1.通过Statement *** 作和访问数据库2.通过ResultSet执行select3.PreparedStatement添加 *** 作4.将获取连接以及释放连接代码封装到JDBCUtils5.通过PreparedStatement对数据进行修改6.PreparedStatement通用增删改方法7.PreparedStatement通用查询方法8.ORM编程思想 四、JDBC实现用户登录功能
1.业务介绍2.登录界面初始化3.登录实现 五、JDBC高级
1.什么是SQL注入2.如何解决SQL注入3.批量插入数据 六、Blob数据类型
1.MySql Blob类型2.添加数据 *** 作3.读取Blob类型数据4.特殊情况 七、JDBC事务
1.JDBC事务概述2.JDBC事务实现 八、数据库连接池
1.数据库连接池相关介绍 九、c3p0连接池
1.c3p0的基本使用2.通过配置xml的方式来使用c3p0 十、DBCP数据库连接池
1.DBCP基本使用2.DBCP配置文件使用方式 十一、druid连接池
1.druid基本使用2.通过druid重构JDBCUtils 十二、JDBC_DAO模式
1. 应用程序分层2.通用baseDAO实现3.实现UserDAO 十三、DbUtils工具
1.QueryRunner2.通过QueryRunner添加数据3.ResultSetHandler4.通过QueryRunner查询数据5.通过QueryRunner查询特殊数据6.自定义ResultSetHandler 十四、JDBC分页技术
1.JDBC分页2.MySql实现分页查询
一、JDBC简介 1.JDBC是什么?
前期准备工作:
1.在工程下新建lib文件夹
2.将jar包导入到lib目录下
3.将导入的jar包通过Add as library添加到项目中
4.创建相关包和测试类
5.在数据库中新建数据库
6.重要知识点:
//获取JDBC连接方法一 public class jdbc_Test { public static void main(String[] args) throws SQLException { //加载驱动 Driver driver = new com.mysql.jdbc.Driver(); //定义url String url = "jdbc:mysql://localhost:3306/baizhan?useSSL=false"; //通过Properties设置账号密码 Properties info = new Properties(); info.setProperty("user","root"); info.setProperty("password","mysql"); //通过Connection连接 Connection conn = driver.connect(url,info); System.out.println(conn); } }2.获取数据库连接方法二
通过反射方法获取driver对象
此方法无第三方API,有助于代码移植以及兼容性
//获取数据库连接方法二 public class jdbc_Test2 { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException { Class clazz = Class.forName("com.mysql.jdbc.Driver"); Driver driver = (Driver) clazz.newInstance(); String url = "jdbc:mysql://localhost:3306/baizhan?useSSL=false"; Properties info = new Properties(); info.setProperty("user","root"); info.setProperty("password","mysql"); Connection conn = driver.connect(url,info); System.out.println(conn); } }3.获取数据库连接方法三
通过驱动管理器 DriverManager 代替 Drive 获取连接
//获取数据库连接方法三 public class jdbc_Test3 { //用DriverManager 代替 Driver public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException { //用反射获取driver具有良好的代码移植性 Class clazz = Class.forName("com.mysql.jdbc.Driver"); Driver driver = (Driver) clazz.newInstance(); //将driver注册到DriverManager中 DriverManager.registerDriver(driver); String url = "jdbc:mysql://localhost:3306/baizhan?useSSL=false"; String user = "root"; String password = "mysql"; Connection conn = DriverManager.getConnection(url,user,password); System.out.println(conn); } }4.获取数据库连接方法四
//获取数据库连接方法四 public class jdbc_Test4 { public static void main(String[] args) throws ClassNotFoundException, SQLException { //当com.mysql.jdbc.Driver加载到内存虚拟机中时,在Driver类中有static块会自动将Driver注册到DriverManager中 Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/baizhan?useSSL=false"; String user = "root"; String password = "mysql"; Connection conn = DriverManager.getConnection(url,user,password); System.out.println(conn); } }5.获取数据库连接方法五(推荐)
将配置文件与程序分离开
优点:
1.实现数据与代码的分离,实现了解耦
2.如果要修改可直接修改配置文件,可以避免程序重打包
//获取数据库连接方法五(推荐) public class jdbc_Test5 { public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException { //将配置文件读入 InputStream is = jdbc_Test5.class.getClassLoader().getResourceAsStream("jdbc.properties"); Properties properties = new Properties(); //读入数据 properties.load(is); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String url = properties.getProperty("url"); String driverClass = properties.getProperty("driverClass"); Class.forName(driverClass); Connection conn = DriverManager.getConnection(url,user,password); System.out.println(conn); } }三、JDBC基本 *** 作
1.通过Statement *** 作和访问数据库int execute(String sql); //执行insert、update、delete *** 作
ResultSet executeQuery(String sql); //执行查询 *** 作
Statement的使用
//通过Statement *** 作和访问数据库 public class Statement_Test { public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException { //获取数据库连接 InputStream is = jdbc_Test5.class.getClassLoader().getResourceAsStream("jdbc.properties"); Properties properties = new Properties(); properties.load(is); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String url = properties.getProperty("url"); String driverClass = properties.getProperty("driverClass"); Class.forName(driverClass); Connection conn = DriverManager.getConnection(url,user,password); //获取statement对象 Statement statement = conn.createStatement(); //拼接sql Scanner sc = new Scanner(System.in); System.out.println("请输入账户:"); String username = sc.next(); System.out.println("请输入密码:"); String userpassword = sc.next(); String sql = "insert into user(username,userpassword) values('" + username + "','" + userpassword + "')"; //执行sql statement.execute(sql); //关闭资源 conn.close(); statement.close(); } }2.通过ResultSet执行select
//通过ResultSet执行select public class Statement_Test2 { public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException { //获取数据库连接 InputStream is = jdbc_Test5.class.getClassLoader().getResourceAsStream("jdbc.properties"); Properties properties = new Properties(); properties.load(is); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String url = properties.getProperty("url"); String driverClass = properties.getProperty("driverClass"); Class.forName(driverClass); Connection conn = DriverManager.getConnection(url,user,password); //获取statement对象 Statement statement = conn.createStatement(); String sql = "select * from user"; ResultSet rs = statement.executeQuery(sql); while(rs.next()){ System.out.println(rs.getString("username")+" "+rs.getString("userpassword")); } conn.close(); statement.close(); rs.close(); } }3.PreparedStatement添加 *** 作
//PreparedStatement添加 *** 作 public class Statement_Test3 { public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException { //获取数据库连接 InputStream is = jdbc_Test5.class.getClassLoader().getResourceAsStream("jdbc.properties"); Properties properties = new Properties(); properties.load(is); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String url = properties.getProperty("url"); String driverClass = properties.getProperty("driverClass"); Class.forName(driverClass); Connection conn = DriverManager.getConnection(url,user,password); //创建PreparedStatement对象 String sql = "insert into user(username,userpassword) values(?,?)"; PreparedStatement ps = conn.prepareStatement(sql); //填充占位符 ps.setString(1,"admin6"); ps.setString(2,"123456"); //执行添加 ps.executeUpdate(); //关闭资源 ps.close(); conn.close(); } }4.将获取连接以及释放连接代码封装到JDBCUtils
为了统一对Connection资源的管理及使用,创建JDBCUtils工具类,实现对数据库的连接与释放进行统
一管理。
//将获取连接以及释放连接代码封装到JDBCUtils public class JDBCUtils { //获取连接 public static Connection getConnection() throws IOException, ClassNotFoundException, SQLException { InputStream is = jdbc_Test5.class.getClassLoader().getResourceAsStream("jdbc.properties"); Properties properties = new Properties(); properties.load(is); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String url = properties.getProperty("url"); String driverClass = properties.getProperty("driverClass"); Class.forName(driverClass); Connection conn = DriverManager.getConnection(url,user,password); return conn; } //关闭资源 *** 作 public static void close(Connection conn,Statement statement) throws SQLException { if (conn != null){ conn.close(); } if (statement != null){ statement.close(); } } }5.通过PreparedStatement对数据进行修改
//通过PreparedStatement对数据进行修改 public class PreparedStatement_Test2 { public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException { //获取连接并创建PreparedStatement对象 Connection conn = JDBCUtils.getConnection(); String sql = "update user set username = ? where id = ?"; PreparedStatement ps = conn.prepareStatement(sql); //填充占位符 ps.setObject(1,"admintest"); ps.setInt(2,1); //执行修改 ps.executeUpdate(); //关闭资源 JDBCUtils.close(conn,ps); } }6.PreparedStatement通用增删改方法
//PreparedStatement通用增删改方法 public class Statement_Test4 { public static void main(String[] args) throws Exception { String sql = "delete from user where id = ? or id = ?"; update(sql,1,2); } public static void update(String sql,Object...args) throws Exception { Connection conn = JDBCUtils.getConnection(); PreparedStatement ps = conn.prepareStatement(sql); for (int i = 0; i 7.PreparedStatement通用查询方法//PreparedStatement通用查询方法 public class PreparedStatement_Test3 { public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException { String sql = "select * from user where id < ?"; query(sql,6); } public static void query(String sql,Object...args) throws SQLException, IOException, ClassNotFoundException { Connection conn = JDBCUtils.getConnection(); PreparedStatement ps = conn.prepareStatement(sql); for (int i = 0;i 8.ORM编程思想//ORM编程思想 public class PreparedStatement_Test4 { public static void main(String[] args) throws ClassNotFoundException, SQLException, NoSuchFieldException, IllegalAccessException, IOException { String sql = "select * from user where id < ?"; Listusers = queryUser(sql,6); System.out.println(); } public static List queryUser(String sql,Object...args) throws SQLException, IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException { //获取Connection Connection conn = JDBCUtils.getConnection(); //预处理 PreparedStatement ps = conn.prepareStatement(sql); //设置不定参参数 for (int i=0;i users = new ArrayList<>(); //查询 *** 作 ResultSet rs = ps.executeQuery(); //获取元数据 ResultSetmetaData rsmd = rs.getmetaData(); //获取列数 int columnCount = rsmd.getColumnCount(); while (rs.next()){ User u = new User(); for (int i=0;i 四、JDBC实现用户登录功能 1.业务介绍 2.登录界面初始化 //用户登录功能_登录界面初始化 public class Login { public static void main(String[] args) { initUI(); } public static Map3.登录实现initUI(){ Scanner sc = new Scanner(System.in); System.out.println("请输入账号:"); String account = sc.next(); System.out.println("请输入密码:"); String password = sc.next(); Map userLoginInfo = new HashMap<>(); userLoginInfo.put("account",account); userLoginInfo.put("password",password); return userLoginInfo; } } Account实体类
//Account实体类 public class Account { private Integer userid; private String useraccount; private String username; private String userpassword; public Integer getUserid() { return userid; } public void setUserid(Integer userid) { this.userid = userid; } public String getUseraccount() { return useraccount; } public void setUseraccount(String useraccount) { this.useraccount = useraccount; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getUserpassword() { return userpassword; } public void setUserpassword(String userpassword) { this.userpassword = userpassword; } }针对account表实现通用查询
//针对account表实现通用查询 public static List queryAccount(String sql,Object...args) throws Exception{ List accounts = new ArrayList<>(); //获取数据库的连接 Connection conn = JDBCUtils.getConnection(); //预编译sql语句,返回PrepareStatement的实例 PreparedStatement ps = conn.prepareStatement(sql); //填充占位符 for (int i=0;i登录实现
//登录实现 public static boolean login(MapuserLoginInfo) throws Exception{ //定义sql String sql = "select * from account where useraccount = ? and userpassword = ?"; //获取所有匹配账号密码的account对象 List accounts = queryAccount(sql,userLoginInfo.get("account"),userLoginInfo.get("password")); //如果该集合为0,代表账号或密码没有匹配,登陆失败 if (accounts.size() == 0){ return false; } return true; } 测试登录功能
public static void main(String[] args) throws Exception { Map五、JDBC高级 1.什么是SQL注入userLoginInfo = initUI(); System.out.println(login(userLoginInfo)?"登录成功":"登录失败"); } SQL注入是指利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的
SQL语句段或者命令,从而利用系统的SQL引擎完成恶意行为的做法。
例如当使用Statement实现时:Statement statement = conn.createStatement();SQL语句改为:
String sql = "select * from account where useraccount = '" +userLoginInfo.get("account")+ "' and userpassword = '" + userLoginInfo.get("password") +"'";当你测试时:
以上输入的账号和密码,通过SQL拼接,在执行过程中的SQL实际上是:select * from account where useraccount = 'zhangsan' and userpassword ='baizhan'or'1=1'由于1=1永远成立,所以不论账号密码是否正确,都会返回正确。
导致SQL注入的根本原因:
2.如何解决SQL注入
用户输入的信息中包含SQL语句的关键字,并且这些关键字参与SQL语句的编译过程,导致SQL语句的原意被扭曲,进而达到SQL注入的目的。只要用户提供的信息不参与SQL语句的编译过程,即使用户提供的信息中包含SQL语句的关键字,但是
没有参与编译,仍然不起作用。PreparedStatement可以将信息参数化,仍然用PreparedStatement实现登录功能:
PreparedStatement ps = conn.prepareStatement(sql);
以上输入的账号和密码,通过PreparedStatement预编译,将baizhan’or’1=1作为一个整体的字符串参
数设置到SQL当中,在执行过程中的SQL实际上是:select * from account where useraccount = 'zhangsan' and userpassword ="baizhan'or'1=1"3.批量插入数据利用三种不同的方法插入数据,并测试其用时。
首先通过Navicat创建一张物品空表:CREATE TABLE goods(id int PRIMARY key auto_increment,goodsname VARCHAr(25))
依次用三种方法向表中插入2000条数据:
方法一、通过Statement + for循环方式批量插入数据,计算执行时间://1. 通过Statement + for循环方式批量插入数据,计算执行时间 public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException { Connection conn = JDBCUtils.getConnection(); Statement statement = conn.createStatement(); //获取起始时间 Long start = System.currentTimeMillis(); for (int i=0;i<2000;i++){ String sql = "insert into goods(goodsname)values('name_"+i+"')"; statement.execute(sql); } //获取结束时间 Long end = System.currentTimeMillis(); JDBCUtils.close(conn,statement); System.out.println("插入总用时为:"+(end-start));由于此方法使用的是statement,所以每次需要重新生成sql字符串。结果如下:
方法二、通过PreparedStatement + for循环方式批量插入数据,计算执行时间://2. 通过PreparedStatement + for循环方式批量插入数据,计算执行时间 public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException { Connection conn = JDBCUtils.getConnection(); String sql = "insert into goods(goodsname)value(?)"; PreparedStatement psmt = conn.prepareStatement(sql); Long start = System.currentTimeMillis(); for (int i=0;i<2000;i++){ psmt.setObject(1,"name_"+ i); psmt.executeUpdate(); } Long end = System.currentTimeMillis(); JDBCUtils.close(conn,psmt); System.out.println("插入总用时为:"+(end-start)); }方法二使用的是PreparedStatement,PreparedStatement是预编译模式,DBServer的编译器编
译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数
直接传入就可以执行。结果如下:
方法三、通过PreparedStatement的addBatch()和executeBatch()进行批量插入数据1. addBatch()把若干SQL语句装载到一起,然后一次性传送到数据库执行,即是批量处理sql数
据的。
2. executeBatch()会将装载到一起的SQL语句执行。
3. clearBatch()清除缓存注:MySql默认情况下是不支持批处理的但从5.1.13开始添加了一个rewriteBatchStatement的参数,让MySql支持批处理。在加载url时设置该参数:rewriteBatchedStatements=true
url=jdbc:mysql://localhost:3306/baizhan?useSSL=false&rewriteBatchedStatements=true
public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException { Connection conn = JDBCUtils.getConnection(); String sql = "insert into goods(goodsname)value(?)"; PreparedStatement psmt = conn.prepareStatement(sql); Long start = System.currentTimeMillis(); for (int i=0;i<=2000;i++){ psmt.setObject(1,"name_"+i); //缓存sql psmt.addBatch(); //每500条缓存执行一次 if (i%500==0){ //批量执行sql psmt.executeBatch(); //清除缓存 psmt.clearBatch(); } } Long end = System.currentTimeMillis(); JDBCUtils.close(conn,psmt); System.out.println("插入总用时为: "+(end - start)); }结果:
六、Blob数据类型 1.MySql Blob类型
2.添加数据 *** 作
向演员名单表格中添加图片
public class Blob_Test { //添加 *** 作 public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException { Connection conn = JDBCUtils.getConnection(); String sql = "insert into movieactor(actorname,photo)values(?,?)"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1,"朱茵"); InputStream is = new FileInputStream(new File("C:/actorimg/zhuyin.jpg")); ps.setBlob(2,is); ps.executeUpdate(); JDBCUtils.close(conn,ps); } }3.读取Blob类型数据//读取数据 public class Blob_Test2 { public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException { Connection conn = JDBCUtils.getConnection(); String sql = "select * from movieactor where photo != ''"; PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery(); while(rs.next()){ int id = rs.getInt("id"); String name = rs.getString("actorname"); Blob blob = rs.getBlob("photo"); InputStream is = blob.getBinaryStream(); FileOutputStream fos = new FileOutputStream(id+"_"+name+".jpg"); byte[] Buffer = new byte[1024]; int len; while((len = is.read(Buffer))!=-1){ fos.write(Buffer,0,len); } is.close(); fos.close(); } JDBCUtils.close(conn,ps); } }4.特殊情况当读入一张7M左右的照片时,会出现报错
public class Blob_Test3 { public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException { Connection conn = JDBCUtils.getConnection(); String sql = "insert into movieactor(actorname,photo)value(?,?)"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1,"照片"); InputStream is = new FileInputStream(new File("C:/actorimg/photo.jpg")); ps.setBlob(2,is); ps.executeUpdate(); JDBCUtils.close(conn,ps); } }报错:
Exception in thread “main” com.mysql.jdbc.PacketTooBigException: Packet for query is too large (8056021 > 4194304). You can change this value on the server by setting the max_allowed_packet’ variable.
原因:虽然MediumBlob允许保存最大值为16M,但MySql默认允许值为4194304即4M。
七、JDBC事务 1.JDBC事务概述
解决:在my.ini中添加max_allowed_packet=16M,并重启MySql服务。
文件路径:C:ProgramDataMySQLMySQL Server 5.7my.ini
并重启Mysql服务。2.JDBC事务实现
银行转账业务:
非事务实现:加载相关数据,导入bank.sql
由zhangsan向lisi转账500public static void main(String[] args) throws SQLException { Connection conn = null; PreparedStatement psmt = null; try{ conn = JDBCUtils.getConnection(); String sql = "update bank set balance = balance + ? where accountname = ?"; psmt = conn.prepareStatement(sql); //lisi账户增加500 psmt.setObject(1,500); psmt.setObject(2,"lisi"); psmt.executeUpdate(); //zhangsan账户减少500 psmt.setObject(1,-500); psmt.setObject(2,"zhangsan"); psmt.executeUpdate(); }catch (Exception ex){ System.out.println(ex.getMessage()); }finally { JDBCUtils.close(conn,psmt); } }如果在两个executeUpdate()之间发生异常,则部分转账正常,部分转账异常
模拟异常://lisi账户增加500 psmt.setObject(1,500); psmt.setObject(2,"lisi"); psmt.executeUpdate(); //zhangsan账户减少500 //模仿异常 int i = 1 / 0; psmt.setObject(1,-500); psmt.setObject(2,"zhangsan"); psmt.executeUpdate();运行结果:
由于两次SQL *** 作之间出现异常,所以只有部分转账成功。
解决:事务实现:
在获取数据库连接之后,通过Connection对象开启事务public static void main(String[] args) throws SQLException { Connection conn = null; PreparedStatement psmt = null; try{ conn = JDBCUtils.getConnection(); //开启事务 conn.setAutoCommit(false); String sql = "update bank set balance = balance + ? where accountname = ?"; psmt = conn.prepareStatement(sql); //lisi账户增加500 psmt.setObject(1,500); psmt.setObject(2,"lisi"); psmt.executeUpdate(); //zhangsan账户减少500 psmt.setObject(1,-500); psmt.setObject(2,"zhangsan"); psmt.executeUpdate(); //如果没出错,提交事务 conn.commit(); }catch (Exception ex){ //如果出错,回滚事务 conn.rollback(); System.out.println(ex.getMessage()); }finally { JDBCUtils.close(conn,psmt); } }八、数据库连接池 1.数据库连接池相关介绍JDBC数据库连接池的必要性
九、c3p0连接池 1.c3p0的基本使用
数据库连接池
数据库连接池的优点
常用的数据库连接池
public class C3P0_Test { public static void main(String[] args) throws Exception { ComboPooledDataSource cpds = new ComboPooledDataSource(); //配置JDBC相关数据 cpds.setDriverClass("com.mysql.jdbc.Driver"); cpds.setJdbcUrl("jdbc:mysql://localhost:3306/baizhan"); cpds.setUser("root"); cpds.setPassword("mysql"); //设置初始化时,数据库连接池的连接数量 cpds.setInitialPoolSize(10); //获取连接 Connection conn = cpds.getConnection(); System.out.println(conn); } }2.通过配置xml的方式来使用c3p0在src目录下添加名为c3p0-config.xml文件在c3p0-config.xml配置内容如下:
com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/baizhan root mysql 5 10 10 100 200 2 从c3p0连接池中获取Connection连接
//使用默认的数据库连接池 ComboPooledDataSource cpds = new ComboPooledDataSource(); Connection conn = cpds.getConnection(); System.out.println(conn);也可以在c3p0-config.xml设置多个数据库连接池,根据连接池名字不同,来初始化不同的连接池。
如下的配置中,有两个数据库连接池配置com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/baizhan root mysql 5 10 10 100 200 2 com.mysql.jdbc.Driver jdbc:mysql://xxx.xxx.xxx.xxx:3306/bjsxt root root 通过named-config中的name属性的值,来初始化不同的数据库连接池
//获取名为localc3p0连接池 ComboPooledDataSource cpds = new ComboPooledDataSource("localc3p0"); Connection conn = cpds.getConnection(); System.out.println(conn);十、DBCP数据库连接池 1.DBCP基本使用导入commons-dbcp2-2.5.0.jar包及其依赖包commons-pool2-2.6.0.jar、commons-logging1.2.jar到lib目录下,并引入项目中从dbcp连接池中获取Connection连接
public class DBCP_Test { public static void main(String[] args) throws SQLException { BasicDataSource source = new BasicDataSource(); source.setDriverClassName("com.mysql.jdbc.Driver"); source.setUrl("jdbc:mysql://localhost:3306/baizhan"); source.setUsername("root"); source.setPassword("mysql"); source.setInitialSize(10); Connection conn = source.getConnection(); System.out.println(conn); } }2.DBCP配置文件使用方式在src下创建一个dbcp.properties类型的文件,并写入
url=jdbc:mysql://localhost:3306/baizhan driverClassName=com.mysql.jdbc.Driver username=root password=mysql initialSize=10 maxActive=20加载配置文件,获取连接池对象,通过该连接池对象获取连接
//DBCP配置文件使用方式 public static void main(String[] args) throws Exception { //将配置文件以流的方式加载 InputStream is = DBCP_Test2.class.getClassLoader().getResourceAsStream("dbcp.properties"); //创建配置文件 Properties properties = new Properties(); //加载流 properties.load(is); //创建连接池对象 DataSource ds = BasicDataSourceFactory.createDataSource(properties); //获取连接 Connection conn = ds.getConnection(); System.out.println(conn); }十一、druid连接池druid是阿里提供的数据库连接池,据说是集DBCP、c3p0、proxool优点于一身的数据库连接池,目前
1.druid基本使用
经常使用。导入druid-1.0.19.jar包到lib目录下,并引入到项目中在src下创建一个druid.properties类型的文件,并写入
url=jdbc:mysql://localhost:3306/baizhan driverClassName=com.mysql.jdbc.Driver username=root password=mysql initialSize=10 maxActive=20druid配置信息:
加载配置文件,获取连接池对象,通过该连接池对象获取连接
public static void main(String[] args) throws Exception { //将配置文件以流的方式加载 InputStream is = Druid_Test.class.getClassLoader().getResourceAsStream("druid.properties"); //创建配置文件 Properties properties = new Properties(); //加载流 properties.load(is); //创建连接池对象 DataSource ds = DruidDataSourceFactory.createDataSource(properties); //获取连接 Connection conn = ds.getConnection(); System.out.println(conn); }2.通过druid重构JDBCUtils//通过druid重构JDBCUtils public class JDBCUtilsDruid { private static DataSource ds = null; static { //将配置文件以流的方式加载 InputStream is = Druid_Test.class.getClassLoader().getResourceAsStream("druid.properties"); //创建配置文件 Properties properties = new Properties(); try { //加载流 properties.load(is); //创建连接池对象 ds = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } //获取连接 public static Connection getConnection() throws SQLException { Connection conn = ds.getConnection(); return conn; } // 释放数据库连接方法 public static void close(Connection conn, Statement statement) throws SQLException { if (conn != null){ conn.close(); } if (statement != null){ statement.close(); } } }十二、JDBC_DAO模式 1. 应用程序分层应用程序通过创建不同的包来实现项目的分层,将项目中的代码根据功能做具体划分,并存放在不同的
2.通用baseDAO实现
包下。
DAO:Data Access Object访问数据库信息的类和接口,包括了对数据的CRUD(Create、Retrival、Update、Delete)、而不包含任何业务相关的信息。
DAO一般是提供从数据库 增加、删除、修改记录、查询所有记录、查询符合某个条件记录、取得某条记录等方法的底层数据 *** 作自定义类。由于可能 *** 作多个数据库表,这样就需要为每个表提供一个 *** 作他的类 xxDAO, 这些DAO继承baseDAO 就可以省略很多重复代码(从数据库 增加、删除、修改记录、查询所有记录、查询符合某个条件记录、取得某条记录等方法的代码)。
实现一个通用的baseDao抽象类
public abstract class baseDao{ //定义一个变量来接受泛型的类型 private Class type; //获取T的Class对象,获取泛型类型,泛型是在被子类继承时才确定 public baseDao(){ //获取子类类型 Class clazz = this.getClass(); //获取父类类型 //getGenericSuperclass()用来获取当前类的父类的类型 //ParameterizedType表示的是带泛型的类型 ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass(); //获取具体的泛型类型 //getActualTypeArguments()获取具体的泛型类型 //这个方法返回一个Type类型数组 Type[] types = parameterizedType.getActualTypeArguments(); //获取具体的泛型类型 this.type =(Class ) types[0]; } } 2. 通用的增删改 *** 作
//通用增删改 *** 作 public int excuteUpdate(String sql,Object...param) throws Exception{ //获取连接 Connection conn = JDBCUtilsDruid.getConnection(); PreparedStatement psmt = conn.prepareStatement(sql); //绑定参数 for (int i=0;i3. 用的查询 *** 作(需要用到commons-beanutils-1.9.3.jar包及其依赖包commons-logging-1.2.jar,将它们导入并引入工程)
//通用查询方法,返回零条或多条查询记录 public ListgetBean(String sql,Object...param) throws Exception{ List list = new ArrayList<>(); //获取连接 Connection conn = JDBCUtilsDruid.getConnection(); PreparedStatement psmt = conn.prepareStatement(sql); //绑定参数 for (int i=0;i 4. 获取单一值,如select(*)
//获取单一值,如select(*),select max(date)等等 public Object getValue(String sql,Object...param) throws Exception{ Object res = null; Connection conn = JDBCUtilsDruid.getConnection(); PreparedStatement psmt = conn.prepareStatement(sql); //绑定参数 for (int i=0;i3.实现UserDAO 创建UserDAO接口
public interface UserDAO { //根据username获取一条记录 User getUser(String username) throws Exception; //插入一条User void insertUser(User user) throws Exception; //根据id删除一条数据 void deleteUserById(Integer id) throws Exception; //获取一共有多少用户 Integer getUserCount() throws Exception; }2 . 创建UserDAO的实现类UserDAOImpl,UserDAOImpl继承baseDAO
(由于每个方法都要抛出异常,所以在接口UserDAO的方法后面也会throw异常)public class UserDAOImpl extends baseDaoimplements UserDAO { //根据username获取一条记录 @Override public User getUser(String username) throws Exception { User u = null; String sql = "select * from user where username = ?"; List list = this.getBean(sql,username); if (list.size() != 0 ){ u = list.get(0); } return u; } //插入一条User @Override public void insertUser(User user) throws Exception { String sql = "insert into user(username,userpassword)value(?,?)"; this.excuteUpdate(sql,user.getUsername(),user.getUserpassword()); } //根据id删除一条数据 @Override public void deleteUserById(Integer id) throws Exception { String sql = "delete from user where id = ?"; this.excuteUpdate(sql,id); } //获取一共有多少用户 @Override public Integer getUserCount() throws Exception { String sql = "select count(*) from user"; Integer count = Integer.valueOf(this.getValue(sql).toString()); return count; } } 测试各个方法
//测试UserDAO public class Main { public static void main(String[] args) throws Exception { UserDAO userDAO = new UserDAOImpl(); //测试insertuser //测试get //测试delete // userDAO.deleteUserById(7); //获取用户总数 System.out.println(userDAO.getUserCount()); } }十三、DbUtils工具 1.QueryRunner 2.通过QueryRunner添加数据//通过QueryRunner添加数据 public class DBUtils_Test { public static void main(String[] args) throws Exception { InputStream is = DBUtils_Test.class.getClassLoader().getResourceAsStream("druid.properties"); Properties properties = new Properties(); properties.load(is); //通过数据库连接池初始化QueryRunner对象 QueryRunner queryRunner = new QueryRunner(DruidDataSourceFactory.createDataSource(properties)); String sql = "insert into user(username,userpassword)values(?,?)"; //count代表影响了几行记录 int count = queryRunner.update(sql,"QueryRunnerTest","QueryRunnner"); System.out.println(count); } }3.ResultSetHandler 4.通过QueryRunner查询数据返回单条记录并封装成实体类对象
//返回单条记录并封装成实体类对象 public class DBUtils_Test2 { public static void main(String[] args) throws Exception { InputStream is = DBUtils_Test2.class.getClassLoader().getResourceAsStream("druid.properties"); Properties properties = new Properties(); properties.load(is); QueryRunner queryRunner = new QueryRunner(DruidDataSourceFactory.createDataSource(properties)); String sql = "select * from user where id = ?"; //一条记录使用BeanHandler //给BeanHandler提供相关实体类信息 BeanHandlerbh = new BeanHandler<>(User.class); //使用实体类对象直接接收数据 //query参数,分别为sql语句,ResultSetHandler对象,及sql语句中的占位符参数 User user = queryRunner.query(sql,bh,8); System.out.println(user.getUsername()); } } 返回多条记录并封装成实体类对象列表
//返回多条记录并封装成实体类对象列表 public class DBUtils_Test3 { public static void main(String[] args) throws Exception { InputStream is = DBUtils_Test3.class.getClassLoader().getResourceAsStream("druid.properties"); Properties properties = new Properties(); properties.load(is); QueryRunner queryRunner = new QueryRunner(DruidDataSourceFactory.createDataSource(properties)); String sql = "select * from user"; //多条记录使用BeanListHandler //给BeanListHandler提供相关实体类信息 BeanListHandler5.通过QueryRunner查询特殊数据bh = new BeanListHandler<>(User.class); //使用实体类集合直接接收所有数据 //query参数,分别为sql语句,ResultSetHandler对象 List users = queryRunner.query(sql,bh); for (User u : users){ System.out.println(u.getUsername()); } } } 查询User表中一共有多少条数据
//查询User表中一共有多少条数据 public class DBUtils_Test4 { public static void main(String[] args) throws Exception { InputStream is = DBUtils_Test4.class.getClassLoader().getResourceAsStream("druid.properties"); Properties properties = new Properties(); properties.load(is); QueryRunner queryRunner = new QueryRunner(DruidDataSourceFactory.createDataSource(properties)); String sql = "select count(*) from user"; //通过ScalarHandler保存单一值 ScalarHandler sh = new ScalarHandler(); Long count = (Long)queryRunner.query(sql,sh); System.out.println(count); } }6.自定义ResultSetHandler//自定义ResultSetHandler public class MyResultSetHandler implements ResultSetHandler { @Override public Object handle(ResultSet resultSet) throws SQLException { Map十四、JDBC分页技术 1.JDBC分页map = null; if (resultSet.next()){ map = new HashMap<>(); map.put("id",resultSet.getString("id")); map.put("username",resultSet.getString("username")); map.put("userpassword",resultSet.getString("userpassword")); } return map; } public static void main(String[] args) throws Exception { InputStream is = DBUtils_Test.class.getClassLoader().getResourceAsStream("druid.properties"); Properties properties = new Properties(); properties.load(is); QueryRunner queryRunner = new QueryRunner(DruidDataSourceFactory.createDataSource(properties)); String sql = "select * from user where id = ?"; MyResultSetHandler msh = new MyResultSetHandler(); Map map = (Map ) queryRunner.query(sql,msh,8); System.out.println(map); } } jdbc通过分页关键字实现分页效果,将分页结果存在分页对象中
分页类:public class Page { //当前页数 private Integer currPage; //每页显示的记录数 private Integer pageSize; //总记录数 private Integer totalCount; //总页数 private Integer totalPage; //每页显示的数据 private List2.MySql实现分页查询//JDBC分页_Mysql实现 public class MysqlPage { public static void main(String[] args) throws Exception{ Page page = new Page(); //设置当前查询页数 page.setCurrPage(2); //每页大小 page.setPageSize(2); Page respage = selectPage(page); //输出总页数 System.out.println(respage.getTotalPage()); //输出总记录数 System.out.println(respage.getTotalCount()); //输出结果集 System.out.println(respage.getList()); } public static Page selectPage(Page page) throws Exception { Connection conn = JDBCUtilsDruid.getConnection(); String sql = "select * from user limit ?,?"; PreparedStatement ps = conn.prepareStatement(sql); //设置查询页数 (当前页-1)*每页数量 ps.setInt(1,(page.getCurrPage()-1)*page.getPageSize()); //设置每页数量 ps.setInt(2,page.getPageSize()); //执行sql ResultSet rs = ps.executeQuery(); //获取元数据 ResultSetmetaData rsmd = rs.getmetaData(); while (rs.next()){ Mapmap = new HashMap<>(); //根据元数据填充map for (int i=0;i 欢迎分享,转载请注明来源:内存溢出
评论列表(0条)