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);

    扫描二维码关注公众号,回复: 11432968 查看本文章
  • 提交事务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参数,启用批处理
    1. 调用addBatch()方法,添加批处理,放到缓冲区
    2. 设置批处理大小,调用executeBatch(),执行批处理(批处理一次执行多少条需要人为优化)
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表示可为null
				System.out.println("-------------");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JdbcUtil.close(conn, ps);
		}
				
	}

}

猜你喜欢

转载自blog.csdn.net/zdfsb/article/details/107562115
今日推荐