今天,接着上一篇( mysql 数据库 )的基础上,我就写一下 Java 怎样链接数据库,而且操做数据库。html
首先,咱们先来准备一下数据库链接的驱动:java
mysql 的 jar 包下载地址:https://dev.mysql.com/downloads/connector/j/mysql
Oracle 的 jar 包下载地址:https://www.oracle.com/technetwork/cn/middleware/goldengate/downloads/index.htmlsql
本文章还用到 c3p0 的数据库链接池数据库
c3p0 的 jar 包下载地址:https://sourceforge.net/projects/c3p0/apache
接下来,咱们就开始正式了解一下什么是 JDBC ,用 Java 怎样链接数据库,而且怎样操做数据库。编程
JDBC(Java DataBase Connectivity,java数据库链接)是一种用于执行SQL语句的Java API,能够为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此能够构建更高级的工具和接口,使数据库开发人员可以编写数据库应用程序。服务器
咱们安装好数据库以后,咱们的应用程序也是不能直接使用数据库的,必需要经过相应的数据库驱动程序,经过驱动程序去和数据库打交道。其实也就是数据库厂商的JDBC接口实现,即对Connection等接口的实现类的jar文件。oracle
Driver接口由数据库厂家提供,做为java开发人员,只须要使用Driver接口就能够了。在编程中要链接数据库,必须先装载特定厂商的数据库驱动程序,不一样的数据库有不一样的装载方法。如:工具
装载MySql驱动:Class.forName("com.mysql.jdbc.Driver");
装载Oracle驱动:Class.forName("oracle.jdbc.driver.OracleDriver");
Connection与特定数据库的链接(会话),在链接上下文中执行sql语句并返回结果。DriverManager.getConnection(url, user, password)方法创建在JDBC URL中定义的数据库Connection链接上。
链接MySql数据库:Connection conn = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password");
链接Oracle数据库:Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@host:port:database", "user", "password");
链接SqlServer数据库:Connection conn = DriverManager.getConnection("jdbc:microsoft:sqlserver://host:port; DatabaseName=database", "user", "password");
经常使用方法:
使用JDBC的步骤
加载JDBC驱动程序 → 创建数据库链接Connection → 建立执行SQL的语句Statement → 处理执行结果ResultSet → 释放资源
经过初始化驱动类com.mysql.jdbc.Driver,该类就在 mysql-connector-java-5.0.8-bin.jar中。若是你使用的是oracle数据库那么该驱动类将不一样。
//加载数据库驱动程序(对应的 Driver 实现类中有注册驱动的静态代码块.) String driver ="com.mysql.jdbc.Driver"; Class.forName(driver);
//经过 DriverManager 的 getConnection() 方法获取数据库链接. Connection conn = DriverManager.getConnection(url,user,password);
这里须要提供:url包括如下(jdbc:mysql://ip地址:端口号/须要链接的数据库名字),例如:jdbc:mysql://localhost:3306/db_database05
数据库所处于的ip:127.0.0.1 (这里是本机,若是链接其余电脑上的数据库,请改变该ip)
数据库的端口号: 3306 (mysql专用端口号)
数据库名称: (根据你本身数据库中的名称填写)
数据库链接的用户名:user
数据库的登陆密码:password
/* * 数据库链接工具类 */ package com.hzc.util; import java.sql.Connection; import java.sql.DriverManager; public class DataBaseUtil { /** * 获取数据库链接 * @return Connection 对象 */ public static Connection getConnection(){ Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/db_database05"; conn = DriverManager.getConnection(url,user,password); //这里的user和password根据本身的数据库登陆和密码填写 } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 关闭数据库链接 * @param conn Connection 对象 */ public static void closeConnection(Connection conn){ //判断 conn 是否为空 if(conn != null){ try { conn.close(); //关闭数据库链接 } catch (Exception e) { e.printStackTrace(); } } } }
这里在提供 c3p0 数据库链接池的方法
package jdbc; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; /* * 操做JDBC的工具类,其中封装了一些工具方法 */ public class JDBCTools { private static DataSource dataSource = null; //数据库链接池应只初始化一次 static{ dataSource = new ComboPooledDataSource("helloc3p0"); } //数据库链接:经过读取配置文件从数据库服务器获取一个链接 public static Connection getConnection() throws Exception{ return dataSource.getConnection(); } //关闭 ResultSet、Statement 和 Connection public static void release(ResultSet rs,Statement statement,Connection conn){ if(rs != null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(statement != null){ try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } //数据库链接池的 Connection 对象进行 close 时 //并非真的进行关闭, 而是把该数据库链接会归还到数据库链接池中. if(conn != null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } /* * 处理数据库的事务 */ //提交事务 public static void commit(Connection conn){ if(conn != null){ try { conn.commit(); } catch (SQLException e) { e.printStackTrace(); } } } //回滚事务 public static void rollback(Connection conn){ if(conn != null){ try { conn.rollback(); } catch (SQLException e) { e.printStackTrace(); } } } //开始事务 public static void beginTx(Connection conn){ if(conn != null){ try { conn.setAutoCommit(false); } catch (SQLException e) { e.printStackTrace(); } } } }
C3P0 要在 src 目录下配置:建立一个名为 c3p0-config.xml ,而且记住要导入 c3p0 的 jar 包。
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <named-config name="helloc3p0"> <!-- 指定链接数据源的基本属性 --> <property name="user">登陆名</property> <property name="password">密码</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property> <!-- 若数据库中链接数不足时, 一次向数据库服务器申请多少个链接 --> <property name="acquireIncrement">5</property> <!-- 初始化数据库链接池时链接的数量 --> <property name="initialPoolSize">5</property> <!-- 数据库链接池中的最小的数据库链接数 --> <property name="minPoolSize">5</property> <!-- 数据库链接池中的最大的数据库链接数 --> <property name="maxPoolSize">10</property> <!-- C3P0 数据库链接池能够维护的 Statement 的个数 --> <property name="maxStatements">20</property> <!-- 每一个链接同时可使用的 Statement 对象的个数 --> <property name="maxStatementsPerConnection">5</property> </named-config> </c3p0-config>
用于执行静态SQL语句并返回它所生成结果的对象。
三种Statement类:
经常使用Statement方法:
ResultSet提供检索不一样类型字段的方法,经常使用的有:
ResultSet还提供了对结果集进行滚动的方法:
使用后依次关闭对象及链接:ResultSet → Statement → Connection
这里就直接提供数据库通用的查询方法,本身写成一个公用类,须要用查询方法的时候,就能够继承它,调用里面的方法。
package jdbc; /* * JDBC的工具方法 */ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.beanutils.BeanUtils; public class Dao { // 执行 SQL 语句,使用 PreparedStatement public void update(String sql, Object... args) { Connection conn = null; PreparedStatement ps = null; try { conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(null, ps, conn); } } // 执行SQL的方法,使用 Statement:insert、update、delete,而不包含select public void update(String sql) { Connection conn = null; Statement st = null; try { conn = JDBCTools.getConnection(); st = conn.createStatement(); st.executeUpdate(sql); } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(null, st, conn); } } // 查询一条记录,返回对应的对象 public <T> T get(Class<T> clazz, String sql, Object... args)throws Exception { List<T> result = getForList(clazz, sql, args); if (result.size() > 0) { return result.get(0); } return null; } /* * 传入 SQL 语句和 Class 对象,返回 SQL 语句查询的记录对应的 Class 类的对象的集合 * * @param clazz: 对象的类型 * * @param sql: SQL 语句 * * @param args: 填充 SQL 语句的占位符的可变参数 * * @return */ public <T> List<T> getForList(Class<T> clazz, String sql, Object... args)throws Exception { List<T> list = new ArrayList<>(); Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { // 一、获得结果集 conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); // 二、处理结果集,获得 Map 的 List, 其中一个 Map 对象就是一条记录. Map 的 key 为 rs 中列的别名, // Map 的 value 为列的值 List<Map<String, Object>> values = handleResultSetToMapList(rs); // 三、把 Map 的 List 转为 clazz 对应的 List, 其中 Map 的 key 即为 clazz 对应的对象的 // propertyName, // 而 Map 的 value 即为 clazz 对应的对象的 propertyValue list = transfterMapListToBeanList(clazz, values); } catch (Exception e) { e.printStackTrace(); } finally { JDBCTools.release(rs, ps, conn); } return list; } // 把 Map 的 List 转为 clazz 对应的 List public <T> List<T> transfterMapListToBeanList(Class<T> clazz, List<Map<String, Object>> values)throws Exception { List<T> result = new ArrayList<>(); T bean = null; if (values.size() > 0) { for (Map<String, Object> m : values) { bean = clazz.newInstance(); for (Map.Entry<String, Object> entry : m.entrySet()) { String propertyName = entry.getKey(); Object value = entry.getValue(); BeanUtils.setProperty(bean, propertyName, value); } // 把 Object 对象放入到 list 中 result.add(bean); } } return result; } /** * 处理结果集, 获得 Map 的一个 List, 其中一个 Map 对象对应一条记 * * @param resultSet * @return * @throws SQLException */ public List<Map<String, Object>> handleResultSetToMapList(ResultSet rs) throws Exception { // 准备一个 List<Map<String, Object>>:键: 存放列的别名, 值: 存放列的值. 其中一个 Map // 对象对应着一条记录 List<Map<String, Object>> values = new ArrayList<>(); List<String> columnLabels = getColumnLabels(rs); Map<String, Object> map = null; // 处理 ResultSet, 使用 while 循环 while (rs.next()) { map = new HashMap<>(); for (String columnLabel : columnLabels) { Object value = rs.getObject(columnLabel); map.put(columnLabel, value); } // 把一条记录的一个 Map 对象放入 List 中 values.add(map); } return values; } /** * 获取结果集的 ColumnLabel 对应的 List * * @param rs * @return * @throws SQLException */ private List<String> getColumnLabels(ResultSet rs) throws Exception { List<String> labels = new ArrayList<>(); ResultSetMetaData rsmd = rs.getMetaData(); for (int i = 0; i < rsmd.getColumnCount(); i++) { labels.add(rsmd.getColumnLabel(i + 1)); } return labels; } // 返回某条记录的某一个字段的值 或 一个统计的值(一共有多少条记录等.) @SuppressWarnings("unchecked") public <E> E getForValue(String sql, Object... args) { // 1. 获得结果集: 该结果集应该只有一行, 且只有一列 Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { // 1. 获得结果集 conn = JDBCTools.getConnection(); ps = conn.prepareStatement(sql); for (int i = 0; i < args.length; i++) { ps.setObject(i + 1, args[i]); } rs = ps.executeQuery(); if (rs.next()) { return (E) rs.getObject(1); } } catch (Exception ex) { ex.printStackTrace(); } finally { JDBCTools.release(rs, ps, conn); } // 2. 取得结果 return null; } }
掌握好 JDBC 的链接,Java 写不少项目都要与数据库打交道。
本身写的不是专业,但愿你们提一下意见。本身也是在学习 Java 的小白。写一下博客记录一下本身的学习状况。写一下博客,能了解本身学习的水平。