Java JDBC的基础知识(五)

时间:2022-09-04 09:07:16

本文主要记录JDBC基础知识之后的部分内容。另外,我看到《Java核心基础2》中第四章是主要介绍数据库编程的。里面有一些说明和应用特别灵活,有些部分也太容易理解,建议大家看一下。这篇是依然是剩余部分的基础。

一、事务

事务是一组组合成逻辑工作单元的操作,虽然系统中可能会出错,但事务将控制和维护事务中每个操作的一致性和完整性。

事务具有:

1.原子性(atomicity):组成事务处理的语句形成了一个逻辑单元,不能只执行其中的一部分。

2.一致性(consistency):在事务处理执行前后,数据库是一致的(数据库数据完整性约束)。

3.隔离性(isolcation):一个事务处理对另一个事务处理的影响。

4.持续性(durability):事务处理的效果能够被永久保存下来 。

用一副图来说明一下:

Java JDBC的基础知识(五)

Connection.setAutoCommit(false);  //打开事务
Connection.commit(); //揭交事务
Connection.rollback(); //回滚事务

当只想撤销部分操作的时候,可以使用 SavePoint

SavePoint sp=conn.getSavePoint();
conn.rollback(sp);
conn.commit();

代码应用示例:

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List; class AdminInfo {
public static void main(String[] args) {
AdminInfo admin = new AdminInfo();
admin.setId(122);
admin.setAddress("杭州文一西路");
admin.setPassword("123");
admin.setUserName("周周"); List<Integer> roleList = new ArrayList<Integer>();
roleList.add(3);
roleList.add(4);
roleList.add(5); addAdmin(admin, roleList); } private void setId(int i) {
// TODO Auto-generated method stub } private void setAddress(String string) {
// TODO Auto-generated method stub } private void setPassword(String string) {
// TODO Auto-generated method stub } private void setUserName(String string) {
// TODO Auto-generated method stub } private String getPassword() {
// TODO Auto-generated method stub
return null;
} private String getUserName() {
// TODO Auto-generated method stub
return null;
} private String getId() {
// TODO Auto-generated method stub
return null;
} public static void addAdmin(AdminInfo admin, List<Integer> roleList) {
Connection conn = null;
Statement stm = null; try {
conn = DBUtil.getConn();
stm = conn.createStatement(); String sql = "insert into adminInfo (id,userName,password) values ( "
+ admin.getId()
+ ",'"
+ admin.getUserName()
+ "','"
+ admin.getPassword() + "') "; conn.setAutoCommit(false); // 开启事务
stm.execute(sql); for (Integer i : roleList) {
String sql2 = "insert into adminRole(adminid,roleId) values ( "
+ admin.getId() + "," + i + ")";
@SuppressWarnings("unused")
int a = 9 / 0;
stm.execute(sql2);
} conn.commit(); } catch (Exception ex) {
try {
conn.rollback(); // 回滚
} catch (SQLException e) {
e.printStackTrace();
}
ex.printStackTrace();
} finally {
DBUtil.close(null, stm, conn);
} } }

二、带回滚点的事务

从上面的图中,已经可以了解到,带滚点的事务的特点。只要设置了它,程序因为意外原因而中断,也可以当作数据都回到原来的起始点,就当什么事情都没发生过。

代码操作演示:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.util.List; public class Test4 {
static void addUserPointDemo(String userName, String userId,
List<Integer> roleList) {
Connection conn = null;
PreparedStatement stm = null;
Savepoint point = null;
try {
conn = DBUtil.getConn();
String sql = "insert into SysUser (userName,userId) values(?,?)";
stm = conn.prepareStatement(sql);
stm.setString(1, userName);
stm.setString(2, userId); conn.setAutoCommit(false);
stm.executeUpdate(); // 下面是添加权限列表
for (int i = 0; i < roleList.size(); i++) {
if (i == 3) { // 在等于3的时候设置保存点
point = conn.setSavepoint();
}
if (i == 5) {
int a = 2 / 0;
}
String sql2 = "insert into UserRole(userId,roleId) values(?,?)";
stm = conn.prepareStatement(sql2);
stm.setString(1, userId);
stm.setInt(2, roleList.get(i));
stm.executeUpdate();
}
conn.commit(); } catch (Exception e) { // 注意这里的异常类型
try {
conn.rollback(point);
conn.commit(); // 注意 一定要再commit 一次
throw new RuntimeException(e);
} catch (SQLException e1) {
throw new RuntimeException(e1.getMessage());
} }
}
}

三、4 元信息

DatabaseMetaData

ParameterMetaData

ResultSetMetaData

1) DatabaseMetaData

getURL():返回一个String类对象,代表数据库的URL。  //jdbc:mysql://localhost:3306/shop

getUserName():返回连接当前数据库管理系统的用户名。 //root@localhost

getDatabaseProductName():返回数据库的产品名称。  //MySQL

getDatabaseProductVersion():返回数据库的版本号。

getDriverName():返回驱动驱动程序的名称。 //MySQL-AB JDBC Driver

getDriverVersion():返回驱动程序的版本号。 //mysql-connector-java-5.0.4 ( $Date: 2006-10-19 17:47:48 +0200 (Thu, 19 Oct 2006) $, $Revision: 5908 $ )

isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。//false

supportsTransactions()  //true

getSQLKeywords()  //AUTO_INCREMENT,BINARY,BLOB,ENUM,INFILE,LOAD,MEDIUMINT,OPTION,OUTFILE,REPLACE,SET,TEXT,UNSIGNED,ZEROFILL

2) ParameterMetaData(stm.getParameterMetaData();)

getParameterCount(): 获得指定参数的个数

getParameterType(int param):获得指定参数的sql类型  //mysql不支持

代码演示:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet; public class Test5 {
public static AdminInfo login(String sql, Object[] paramList) {
Connection conn = null;
PreparedStatement stm = null;
ResultSet rs = null;
AdminInfo admin = null; try {
conn = DBUtil.getConn();
stm = conn.prepareStatement(sql); /*
* ParameterMetaData pm=stm.getParameterMetaData(); int
* paramCount=pm.getParameterCount();
* System.out.println("该sql一共要"+paramCount+"个参数");
*/ for (int i = 1; i <= paramList.length; i++) {
stm.setObject(i, paramList[i - 1]);
} rs = stm.executeQuery();
if (rs.next()) {
admin = new AdminInfo();
admin.setId(rs.getInt("id"));
admin.setUserName(rs.getString("userName"));
admin.setPassword(rs.getString("password"));
// ...
} } catch (Exception ex) {
ex.printStackTrace();
} finally {
DBUtil.close(null, stm, conn);
}
return admin;
}
}

3) ResultSetMeta (resultSet 的元信息)

getColumnCount()  //得到列数

getColumnName(int colum)  //得到指定列的列名 真名

getColumnLabel(int colum) //得到指定列的列名 as 后的

getColumnTypeName (int column) //得到指定列的类型

代码演示:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData; public class Test6 {
public static AdminInfo test() {
Connection conn = null;
PreparedStatement stm = null;
ResultSet rs = null;
AdminInfo admin = null; try {
conn = DBUtil.getConn();
stm = conn
.prepareStatement("SELECT * FROM ADMININFO where username ='赵明明' and password='123'"); rs = stm.executeQuery();
if (rs.next()) {
ResultSetMetaData rm = rs.getMetaData();
int columnCount = rm.getColumnCount(); // 取列数
for (int i = 1; i <= columnCount; i++) {
System.out.println(rm.getColumnLabel(i)); // 取出所有的列名
} admin = new AdminInfo();
admin.setId(rs.getInt("id"));
admin.setUserName(rs.getString("userName"));
admin.setPassword(rs.getString("password"));
} } catch (Exception ex) {
ex.printStackTrace();
} finally {
DBUtil.close(null, stm, conn);
}
return admin;
}
}

四、数据源和连接池

DataSource 用来取代 DriverManager 来取得Connection 。通过 DataSource 取得连接的速度很快。通过 DataSource 方式取得的连接(Connection ) 是经过代理的,它的close方法,不会导致原来的连接的关闭。一般的 DataSource 内部都有一个连接池来缓存 Connection,可以大大提高效率。这个连接池一般就是 一个 Collection 集合。

例子:简单的数据源模拟

//数据源
public class MyDataSource {
private String url="jdbc:mysql://localhost:3306/shop";
private String user="root";
private String password="admin"; private LinkedList<Connection> connPool=new LinkedList<Connection>(); public MyDataSource(){
for(int i=0;i<10;i++){
this.connPool.addLast(this.createConn());
}
} //对外提供取得连接的方法
public Connection getConn(){
return this.connPool.removeFirst();
} //对外提供收回连接的方法
public void closeConn(Connection conn){
this.connPool.addLast(conn);
} //创建连接
private Connection createConn() {
Connection conn=null;
try {
conn= DriverManager.getConnection(url,user,password);
} catch (SQLException e) {
e.printStackTrace();
} return conn;
} }
 //在DBUtil中使用自定义的数据源
public class DBUtil {
private DBUtil() {} private static MyDataSource myDataSorce=null; //数据源对象
private static String className="com.mysql.jdbc.Driver"; static {
try {
Class.forName(className);
myDataSorce=new MyDataSource();
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
} // 得到连接
public static Connection getConn() {
return myDataSorce.getConn();
} // 关闭连接
public static void close(ResultSet rs, Statement stm, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stm != null) {
try {
stm.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
myDataSorce.closeConn(conn); //关连接的方式也换掉了
} }
}

数据源产品的使用

dbcp DataSource

1) 导入jar 包

commons-collections-3.1.jar

commons-dbcp-1.2.2.jar

commons-pool.jar

配置文件

dbcpconfig.properties

2) 修改配置文件

#连接设置

driverClassName=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/shop

username=root

password=admin

#<!-- 初始化连接 -->

initialSize=10

#最大连接数量

maxActive=50

#<!-- 最大空闲连接 -->

maxIdle=20

#<!-- 最小空闲连接 -->

minIdle=5

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->

maxWait=60000

#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]

#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。

#connectionProperties=useUnicode=true;characterEncoding=gbk

#指定由连接池所创建的连接的自动提交(auto-commit)状态。

#defaultAutoCommit=true

#driver default 指定由连接池所创建的连接的只读(read-only)状态。

#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)

defaultReadOnly=

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。

#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE

defaultTransactionIsolation=READ_UNCOMMITTED

import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory; public class DBUtil {
private DBUtil() {}
private static DataSource dataSource = null; // 数据源对象 static {
try {
// 读dbcp的配置文件
Properties settings = new Properties();
InputStream in = DBUtil.class.getClassLoader().getResourceAsStream( "dbcpconfig.properties");
settings.load(in);
dataSource=BasicDataSourceFactory.createDataSource(settings); } catch (Exception ex) {
ex.printStackTrace();
}
} // 得到连接
public static Connection getConn() {
Connection conn= null;
try {
conn= dataSource.getConnection(); //返回的是一个代理对象
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
} // 关闭连接
public static void close(ResultSet rs, Statement stm, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stm != null) {
try {
stm.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close(); //由于 conn 现在是个代理对象,所以它的close方法并不会真正的关掉连接,而是把它放回边接池中
} catch (SQLException e) {
e.printStackTrace();
}
} } }

Java JDBC的基础知识(五)的更多相关文章

  1. Java JDBC的基础知识(三)

    在前面的Java JDBC的基础知识(二)和(三)中,主要介绍JDBC的原理和简单的应用过程.尤其在(二)中,可以发现代码进行多次try/catch,还有在前面创建连接等过程中好多参数我都给写定了. ...

  2. Java JDBC的基础知识(二)

    在我的上一篇Java JDBC的基础知识(一)中,最后演示的代码在关闭资源的时候,仅仅用了try/catch语句,这里是有很大的隐患的.在程序创建连接之后,如果不进行关闭,会消耗更多的资源.创建连接之 ...

  3. Java JDBC的基础知识(一)

    一.为什么引入JDBC 在学习JDBC之前,抛开它的概念,我先按照我的理解解释一下,为什么要引入JDBC.在我看来,引入JDBC跟我之前学过的引入JVM(Java虚拟机)有些相似之处.当然,关于JVM ...

  4. Java JDBC的基础知识(四)

    之前学习了如何创建一个数据库工具类,如下: import java.sql.Connection; import java.sql.DriverManager; import java.sql.Res ...

  5. JAVA核心技术I---JAVA基础知识(工具类Arrays和Collections类)

    一:工具类 –不存储数据,而是在数据容器上,实现高效操作 • 排序 • 搜索 –Arrays类 –Collection类 二:Arrays类(处理数组) (一)基本方法 –排序:对数组排序, sort ...

  6. JAVA核心技术I---JAVA基础知识(static关键字)

    一:static特殊关键字用处 –变量 –方法 –类 –匿名方法 二:静态变量:类共有成员 –static变量只依赖于类存在(通过类即可访问),不依赖于对象实例存在. –所有的对象实例,对于静态变量都 ...

  7. 【Java面试】基础知识篇

    [Java面试]基础知识篇 Java基础知识总结,主要包括数据类型,string类,集合,线程,时间,正则,流,jdk5--8各个版本的新特性,等等.不足的地方,欢迎大家补充.源码分享见个人公告.Ja ...

  8. 第76节&colon;Java中的基础知识

    第76节:Java中的基础知识 设置环境,安装操作系统,安装备份,就是镜像,jdk配置环境,eclipse下载解压即可使用,下载tomcat 折佣动态代理解决网站的字符集编码问题 使用request. ...

  9. Java面试题-基础知识

    参考文章:Java面试题-基础知识 基础能力 什么是值传递和引用传递 线程状态有哪些,它们之间是如何转换的 进程与线程的区别,进程间如何通讯,线程间如何通讯? HashMap的数据结构是什么?如何实现 ...

随机推荐

  1. 判断是否安装APP

    var time; $('#open').on('click',function(){ window.location="协议";//打开某手机上的某个app应用 time = s ...

  2. Eclipse新增Web项目

    [前置条件] 1. 电脑已安装JDK1.6,并成功配置环境变量 2. 电脑已存在tomcat6.0包,无需安装 [操作步骤] 1. 为eclipse配置tomcat6.0 (1)eclipse菜单栏, ...

  3. 用JS或jQuery访问页面内的iframe&comma;兼容IE&sol;FF

    用JS或jQuery访问页面内的iframe,兼容IE/FF js或者jQuery访问页面中的框架也就是iframe.注意:框架内的页面是不能跨域的! 假设有两个页面,在相同域下. index.htm ...

  4. macbook安装mysql

    一.官网下载dmg文件 二.双击安装dmg文件,一路next: 三.

  5. go语法之一

    Go语法: Go语言要求public的变量必须以 大写字母开头,private变量则以小写字母开头,这种做法不仅免除了public.private关键字,更重要的是统一了命名风格. Go语言对{  } ...

  6. 一些常见的CFD基本概念(飞机为例)&lpar;摘抄&rpar;

    分享一些常见的,常用的但不容易掌握的CFD基础概念. 1.理想气体:不考虑流体粘性的影响. 2.不可压缩流体/恒密度:不考虑流体密度的变化.

  7. C&num; Async&sol;await 异步多线程编程

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.N ...

  8. Gradle笔记——构建基础

    本篇文章主要介绍一下Gradle的构建基础. 它看起来似乎和android项目没多大关系.不能让人一下子理解android项目中的Gradle配置文件,可是这篇基础真的非常重要. 学习Gradle前, ...

  9. 带着萌新看springboot源码04

    继续开头说些废话,我也不知道什么鬼,每次写着写着经常会写到其他地方去了,太容易分神了. 这次说一下springboot对于springmvc的大概整个流程,以请求动态网页为例 . 1.梳理一下spri ...

  10. &lpar;转&rpar;Microsoft Print to PDF

    好像win10.win7 都有