AI智能
改变未来

JDBC访问数据库操作详解(二)之JDBC更多用法:以MySQL为例


JDBC访问数据库操作详解(二)之JDBC更多用法:以MySQL为例

一、返回主键:保存数据后返回生成的主键

​ 利用

Connection.preparedStatement()

的重载方法

PreparedStatement preparedStatement(String sql, int autoGeneratedKeys) throws SQLException

,该方法创建一个默认的

PreparedStatement

对象,该对象具有检索自动生成的键的能力。

int autoGeneratedKeys

——指示是否应返回自动生成的键的标志;常量

Statement.RETURN_GENERATED_KEYS和Statement.NO_GENERATED_KEYS

表示生成的键可/不可用于检索。该方法获取的主键存放在

PreparedStatement

里,通过

PreparedStatement.getGeneratedKeys()

方法获取,该方法返回一个ResultSet。

import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class Test4 {public static void main(String[] args) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;String sql = new StringBuffer().append(\" insert into \").append(\"  t_user  \").append(\"   (username,password,age)   \").append(\" values \").append(\"   (\'zhangsan\',\'123\',18)   \").toString();try {conn = JdbcUtil.getConnection();//传入常量值RETURN_GENERATED_KEYS,表示返回生成的主键ps = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);ps.executeUpdate();//获取存储主键的结果集rs = ps.getGeneratedKeys();while(rs.next()) {//可能是复合主键System.out.println(rs.getInt(1));}} catch (SQLException e) {e.printStackTrace();} finally {JdbcUtil.close(conn, ps);}}}

注:JdbcUtil是数据库工具类,封装了连接数据库和关闭资源的方法,具体可参考我的上一篇博客

二、事务

​ Transaction事务是用来保证数据操作的完整性

  • 一个业务由若干个一次性的操作组成,这些操作要么都成功,要么都失败,如银行转账(对应数据库的多个操作,A给B转钱,在数据库底层要对A做一次更新操作,对B做一次更新操作,对业务而言,这两个操作是一个整体,只有两个操作都成功才算业务成功,如果A操作成功,B操作失败,业务就是失败,那就得回滚——撤销)

  • 事务的四大特性ACID

    原子性(Atomicity):不可再分

    一致性(Consistency):事务执行的前后,数据库是一致的

    隔离性(Isolation):两个事务的操作互不干扰

    持久性(Durability):事务提交后,结果被永久保存下来

    JDBC默认是自动提交事务的,将每一条SQL语句都当作一个独立的事务执行

  • 关闭自动提交事务

    Connection.setAutoCommit(false);

  • 提交事务

    Connection.commit()

  • 回滚事务

    Connection.rollback()

import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;public class Test05 {public static void main(String[] args) {Connection conn = null;PreparedStatement ps = null;try {conn = JdbcUtil.getConnection();//关闭自动提交事务conn.setAutoCommit(false);ps = conn.prepareStatement(\"insert into t_user values (null,\'xxx\',\'111\',20)\");ps.executeUpdate();ps = conn.prepareStatement(\"insert into t_user values (null,\'yyy\',\'111\',20)\");ps.executeUpdate();//提交事务conn.commit();System.out.println(\"同时添加两个用户成功!\");} catch (SQLException e) {//回滚事务try {conn.rollback();System.out.println(\"操作被回滚,出现异常:\"+e.getMessage());} catch (SQLException e1) {e1.printStackTrace();}} finally {JdbcUtil.close(conn, ps);}}}

三、批处理操作

​ 当需要执行的SQL语句比较多时,每次发送一条SQL语句并执行的效率很低,此时可以批量处理并执行SQL

实现步骤:

  1. 在url中添加
    rewriteBatchedStatements=true

    参数,启用批处理[ol]调用addBatch()方法,添加批处理,放到缓冲区

  2. 设置批处理大小,调用executeBatch(),执行批处理(批处理一次执行多少条需要人为优化)

[/ol]

import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;public class Test05 {public static void main(String[] args) {Connection conn = null;PreparedStatement ps = null;try {conn = JdbcUtil.getConnection();//批处理前一般都关闭自动提交事务,防止出错conn.setAutoCommit(false);ps = conn.prepareStatement(\"insert into t_user values (null,?,?,?)\");for(int i = 0;i < 300000; i++) {//30万条ps.setString(1, \"name\" + i);ps.setString(2, \"123\");ps.setInt(3, 18);//添加批处理,放到缓冲区ps.addBatch();//设置批处理大小if(i % 10000 == 0) {//执行批处理ps.executeBatch();//提交事务conn.commit();}}//最后一次可能不足一万条,防止数据没被提交,再执行一次ps.executeBatch();conn.commit();} catch (SQLException e) {e.printStackTrace();} finally {JdbcUtil.close(conn, ps);}}}

事务和批处理的区别:

  • 事务:

    底层是在数据库方存储SQL,没有提交事务的数据放在数据库的临时表空间

    最后一次把临时表空间中的数据提交到数据库服务器执行

    消耗的数据库服务器内存

  • 批处理:

    底层是在客户端存储SQL

    最后一次把客户端存储的数据发送到数据库服务器执行

    消耗的是客户端的内存

四、元数据

​ MetaData元数据是用来描述数据的数据,主要是描述数据属性的信息

​ 分类:

  • 数据库的元数据DatabaseMetaData,获取数据库的名称、版本等信息
  • 结果集的元数据ResultSetMetaData,获取结果集中的列名,列的类型,列的属性等信息
import java.sql.Connection;import java.sql.DatabaseMetaData;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.SQLException;public class Test05 {public static void main(String[] args) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;try {conn = JdbcUtil.getConnection();/** 获取数据库元数据*/DatabaseMetaData dbmd = conn.getMetaData();System.out.println(dbmd.getDatabaseProductName());//获取数据库产品名System.out.println(dbmd.getDatabaseProductVersion());//获取数据库产品版本System.out.println(dbmd.getDriverName());//获取数据库驱动名System.out.println(dbmd.getDriverVersion());//获取数据库驱动版本System.out.println(dbmd.getUserName());//获取数据库用户名ps = conn.prepareStatement(\"select * from t_user\");rs = ps.executeQuery();/** 获取结果集元数据*/ResultSetMetaData rsmd = rs.getMetaData();System.out.println(\"总列数:\" + rsmd.getColumnCount());//获取结果集的总列数for(int i = 1; i <= rsmd.getColumnCount(); i++) {System.out.println(rsmd.getColumnName(i)+\"\\t\"+rsmd.getColumnTypeName(i));//获取列名和列的类型System.out.println(rsmd.getTableName(i));//获取该列所属的表名System.out.println(rsmd.isAutoIncrement(i));//获取该列是否自动增长System.out.println(rsmd.isNullable(i));//获取该列能否为空,0表示为not null,1表示可为nullSystem.out.println(\"-------------\");}} catch (SQLException e) {e.printStackTrace();} finally {JdbcUtil.close(conn, ps);}}}
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » JDBC访问数据库操作详解(二)之JDBC更多用法:以MySQL为例