JDBC连接数据库步骤:
一、加载驱动(先导入mysql-connector-java-5.1.49.jar 右击项目 -> BuildPath -> Configure BuildPath->AddExteranl JARs...)
二、连接数据库
三、使用语句操作数据库
四、关闭数据库连接,释放资源
//驱动
private static String jdbcName = "com.mysql.jdbc.Driver"; /**
*jdbc:mysql://IP 地址:端口号/数据库名称
*jdbc 协议:JDBC URL 中的协议总是 jdbc
*子协议:驱动程序名或数据库连接机制(这种机制可由一个或多个驱动程序支持)的名称,如 mysql
*子名称:一种标识数据库的方法。必须遵循“//主机名:端口/子协议(数据库名)”的标准 URL 命名约定,如 //localhost:3306/test
/
private static String dbUrl = "jdbc:mysql://localhost:3306/test"; private static String user = "root"; private static String password = "root"; public static void main(String[] args) { Connection conn = null; try { //加载驱动 Class.forName(jdbcName); System.out.println("驱动加载成功");
//DriverManager驱动管理类,主要负责获取一个数据库的连接 conn = DriverManager.getConnection(dbUrl, user, password); System.out.println("连接成功"); } catch (ClassNotFoundException e) { e.printStackTrace(); System.err.println("驱动加载失败"); } catch (SQLException e) { e.printStackTrace(); }finally { try { conn.close();//关闭连接 } catch (SQLException e) { e.printStackTrace(); } } }
工具类
import java.sql.Connection; import java.sql.DriverManager; public class DbUitl { private static String jdbcName = "com.mysql.jdbc.Driver"; private static String dbUrl = "jdbc:mysql://localhost:3306/test"; private static String user = "root"; private static String password = "root"; /** * 获取数据库连接 * @return * @throws Exception */ public Connection getCon() throws Exception{ Class.forName(jdbcName); Connection connection = DriverManager.getConnection(dbUrl, user, password); return connection; } /** * 关闭连接 * @param connection * @throws Exception */ public void close(Statement statement,Connection connection) throws Exception{
if(statement != null){
statement.close();
if(connection != null ){
connection.close();
}
}
} }
Statement接口
作用:用于执行静态 SQL 语句并返回它所生成结果的对象。
intexecuteUpdate(String sql) 执行给定 SQL 语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句,或 者不返回任何内容的 SQL 语句(如 SQLDDL 语句)。 voidclose() 立即释放此 Statement 对象的数据库和 JDBC 资源,而不是等待该对象自动关闭时发生此操作
DbUitl dbUitl = new DbUitl(); String sql = "insert into t_book value(null,'java牛逼',888,'B哥',1)"; try { Connection conn = dbUitl.getCon();//获取数据库连接 Statement statement = conn.createStatement();//获取Statement int result = statement.executeUpdate(sql);//可以执行增、删、改操作 System.out.println("操作结果:"+result+"数据"); dbUitl.close(statement,conn);//关闭statement和conn } catch (Exception e) { e.printStackTrace(); }
PreparedStatement接口
PreparedStatement 是 Statement 的子接口,属于预处理操作,与直接使用 Statement 不同的是,PreparedStatement 在操作时,是先在数据表中准备好了一条 SQL 语句,但是此 SQL 语句的具体内容暂时不设置,而是之后再进 行设置。 (以后开发一般用 PreparedStatement,不用 Statement)
DbUitl dbUitl = new DbUitl(); String sql = "insert into t_book value(null,?,?,?,?)"; try { Connection conn = dbUitl.getCon();//获取数据库连接 PreparedStatement prestmt = conn.prepareStatement(sql);//获取Statement prestmt.setString(1, "节哀吧"); prestmt.setFloat(2, 2); prestmt.setString(3, "我"); prestmt.setInt(4, 2); int result = prestmt.executeUpdate(); System.out.println("操作结果:"+result+"数据"); dbUitl.close(prestmt,conn);//关闭preparedStatement和conn } catch (Exception e) { e.printStackTrace(); }
结果集:ResultSet(光标刚开始位于第一行之前)
当我们查询数据库时,返回的是一个二维的结果集,我们这时候需要使用 ResultSet 来遍历结果集,获取每一行 的数据。
使用 ResultSet 遍历查询结果
booleannext() 将光标从当前位置向前移一行。
String getString(int columnIndex) 以 Java 编程语言中 String 的形式获取此 ResultSet 对象的当前行中指定列 的值。
String sql = "select * from t_book"; try { Connection conn = dbUitl.getCon();//获取数据库连接 PreparedStatement prestmt = conn.prepareStatement(sql);//获取Statement //ResultSet 光标刚开始位于第一行之前 ResultSet resultSet = prestmt.executeQuery();//返回结果集 while(resultSet.next()){//光标向前移动一行 int id = resultSet.getInt(1);//获取第一列的值 String bookName = resultSet.getString(2);//获取第二列的值 float price = resultSet.getFloat(3);//获取第三列的值 int bookType = resultSet.getInt(5);//获取第五列的值 System.out.println("id="+id+"bookName="+bookName+"price="+price+"bookType="+bookType); } dbUitl.close(prestmt,conn);//关闭preparedStatement和conn } catch (Exception e) { e.printStackTrace(); }
String getString(String columnLabel) 以 Java 编程语言中 String 的形式获取此 ResultSet 对象的当前行中指 定列的值
String sql = "select * from t_book"; try { Connection conn = dbUitl.getCon();//获取数据库连接 PreparedStatement prestmt = conn.prepareStatement(sql);//获取Statement //ResultSet 光标刚开始位于第一行之前 ResultSet resultSet = prestmt.executeQuery();//返回结果集 while(resultSet.next()){//光标向前移动一行 int id = resultSet.getInt("id");//获取数据库字段为id的值 String bookName = resultSet.getString("bookName");//获取数据库字段为bookName值 float price = resultSet.getFloat("price"); int bookType = resultSet.getInt("bookTypeId"); System.out.println("id="+id+"bookName="+bookName+"price="+price+"bookType="+bookType); } dbUitl.close(prestmt,conn);//关闭preparedStatement和conn } catch (Exception e) { e.printStackTrace(); }
大数据对象处理主要有 CLOB(characterlarge object)和 BLOB(binary large object)两种类型的字段;在 CLOB 中可以存储大字符数据对象,比如长篇小说;在 BLOB 中可以存放二进制大数据对象,比如图片,电影,音乐
处理CLOB(字符大数据对象)
DbUitl dbUitl = new DbUitl(); String sql = "insert into t_book value(null,?,?,?,?,?)"; try { Connection conn = dbUitl.getCon();//获取数据库连接 PreparedStatement prestmt = conn.prepareStatement(sql);//获取Statement prestmt.setString(1, "节哀吧"); prestmt.setFloat(2, 2); prestmt.setString(3, "我"); prestmt.setInt(4, 2); File file = new File("D:\test\LICENSE.txt"); InputStream inputStream = new FileInputStream(file); prestmt.setAsciiStream(5, inputStream, file.length());//数据库字段为longtext int result = prestmt.executeUpdate(); System.out.println("操作结果:"+result+"数据"); dbUitl.close(prestmt,conn);//关闭preparedStatement和conn } catch (Exception e) { e.printStackTrace(); }
String sql = "select * from t_book"; try { Connection conn = dbUitl.getCon();//获取数据库连接 PreparedStatement prestmt = conn.prepareStatement(sql);//获取Statement //ResultSet 光标刚开始位于第一行之前 ResultSet resultSet = prestmt.executeQuery();//返回结果集 while(resultSet.next()){//光标向前移动一行 int id = resultSet.getInt("id");//获取第一列的值 String bookName = resultSet.getString("bookName");//获取第二列的值 float price = resultSet.getFloat("price");//获取第三列的值 int bookType = resultSet.getInt("bookTypeId");//获取第五列的值 Clob c = resultSet.getClob("context");//获取CLOB String context = null; if(c!=null){ context = c.getSubString(1, (int)c.length()); } System.out.println("id="+id+"bookName="+bookName+"price="+price+"bookType="+bookType+"context="+context); } dbUitl.close(prestmt,conn);//关闭preparedStatement和conn } catch (Exception e) { e.printStackTrace(); }
处理BLOB(二进制大数据对象)
File pic = new File("D:\test\1.png"); InputStream inputStream2 = new FileInputStream(pic); prestmt.setBinaryStream(6, inputStream2, pic.length());//数据库类型为longbolb
Blob b = resultSet.getBlob("pic"); if(b!=null){ FileOutputStream fos = new FileOutputStream(new File("d://pic2.png")); fos.write(b.getBytes(1, (int)b.length())); fos.close(); }
CallableStatement 接口:
CallableStatement 主要是调用数据库中的存储过程,CallableStatement 也是 Statement 接口的子接口。在使用 CallableStatement 时可以接收存储过程的返回值。
//存储过程
DELIMITER && CREATE PROCEDURE pro_getBookNameByid(IN bookId INT,OUT bN VARCHAR(20)) BEGIN SELECT bookName INTO bN FROM t_book WHERE id = bookId; END && DELIMITER ;
//数据库执行存储过程
CALL pro_getBookNameByid(1,@bookName);
SELECT @bookName;//查看值
使用 CallableStatement 接口调用存储过程:
voidregisterOutParameter(int parameterIndex, intsqlType) 按顺序位置 parameterIndex 将 OUT 参数注册为 JDBC 类型 sqlType
Connection con = dbUitl.getCon(); String sql = "{CALL pro_getBookNameByid(?,?)}"; CallableStatement cstmt = con.prepareCall(sql); cstmt.setInt(1, 2);//第一个参数 输入参数 id cstmt.registerOutParameter(2, Types.VARCHAR); //第二个参数 输出参数 cstmt.execute(); String bookName = cstmt.getString("bN"); // 获取返回值 dbUitl.close(cstmt, con);
使用 DatabaseMetaData 获取数据库基本信息
DatabaseMetaData 可以得到数据库的一些基本信息,包括数据库的名称、版本,以及得到表的信息。
StringgetDatabaseProductName() 获取此数据库产品的名称。
intgetDriverMajorVersion() 获取此 JDBC 驱动程序的主版本号。
intgetDriverMinorVersion() 获取此 JDBC 驱动程序的次版本号。
Connection con = dbUitl.getCon(); DatabaseMetaData dmd = con.getMetaData(); String dbpn = dmd.getDatabaseProductName();//数据库名称 System.out.println(dbpn);//mysql System.out.println("数据库的版本号:"+ dmd.getDatabaseMajorVersion()+//主版本号 "."+ dmd.getDatabaseMinorVersion()//次版本号 );// 数据库的版本号:5.5
使用 ResultSetMetaData 获取 ResultSet 对象中的信息
ResultSetMetaData 可获取关于 ResultSet 对象中列的基本信息;
intgetColumnCount() 返回此 ResultSet 对象中的列数。
StringgetColumnName(int column) 获取指定列的名称。
intgetColumnTypeName(int column) 获取指定列的 SQL 类型名称
Connection con = dbUitl.getCon(); String sql = "select * from t_book"; PreparedStatement ps = con.prepareStatement(sql); ResultSetMetaData rsmd = ps.getMetaData();//获取结果集的元数据 int num = rsmd.getColumnCount();//获取元数据的总列数 for(int i=1;i<num;i++){ System.out.println(rsmd.getColumnName(i)+","+rsmd.getColumnTypeName(i));//获取每列的列名以及列的sql类型 }
事务:
事务处理在数据库开发中有着非常重要的作用,所谓事务就是所有的操作要么一起成功,要么一起失败,
事务 本身具有原子性(Atomicity)、一致性(Consistency)、隔离性或独立性(Isolation) 、持久性(Durability)4 个特 性,这 4 个特性也被称为 ACID 特征。
原子性:原子性是事务最小的单元,是不可再分隔的单元,相当于一个个小的数据库操作,这些操作必须同时 成功,如果一个失败了,则一切的操作将全部失败。
一致性:指的是在数据库操作的前后是完全一致的,保证数据的有效性,如果事务正常操作则系统会维持有效 性,如果事务出现了错误,则回到最原始状态,也要维持其有效性,这样保证事务开始时和结束时系统处于一 致状态。
隔离性:多个事务可以同时进行且彼此之间无法访问,只有当事务完成最终操作时,才可以看到结果;
持久性:事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。
private static DbUitl dbUitl = new DbUitl();
//转出 public static void outCount(Connection con,String accountName,int account) throws Exception{ String sql = "update t_account set accountBalance = accountBalance - ? where accountName = ?"; PreparedStatement ps = con.prepareStatement(sql); ps.setInt(1, account); ps.setString(2,accountName); ps.executeUpdate(); }
//转入 public static void inCount(Connection con,String accountName,int account) throws Exception{ String sql = "update t_account set accountBalance = accountBalance + ? where accountName = ?"; PreparedStatement ps = con.prepareStatement(sql); ps.setInt(1, account); ps.setString(2,accountName); ps.executeUpdate(); } public static void main(String[] args) { Connection con = null; try { con = dbUitl.getCon(); System.out.println("开始转账"); con.setAutoCommit(false);//取消自动提交 int account = 500; outCount(con, "张三", account); inCount(con, "李四", account); System.out.println("转账结束"); } catch (Exception e) { try { con.rollback();//事务回滚 } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { try { con.commit();//事务提交 con.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
Connection con = null; Savepoint sp = null;//保存点 try { con = dbUitl.getCon(); System.out.println("开始转账"); con.setAutoCommit(false);//取消自动提交 int account = 500; outCount(con, "张三", account); int i = 1/0; sp = con.setSavepoint();//设置保存点 inCount(con, "李四", account); System.out.println("转账结束"); } catch (Exception e) { try { con.rollback(sp);//事务回滚 回滚到保存点 转出成功 转入不管 } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { try { con.commit();//事务提交 con.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }