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

一、事务

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

事务具有:

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

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

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

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

用一副图来说明一下:

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节:Java中的基础知识

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

  9. Java面试题-基础知识

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

随机推荐

  1. Linux的1000个命令

    目录 Linux常用命令 uptime wget uname free who last history pwd cd ls cat head tail tr wc cut diff touch mk ...

  2. cad2020卸载/安装失败/如何彻底卸载清除干净cad2020注册表和文件的方法

    cad2020提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装cad2020失败提示cad2020安装未完成,某些产品无法安装,也有时候想重新安装cad2020 ...

  3. spring boot实现异步调用

    今天在这里学习下使用springboot的异步调用async 首先使用@EnableAsync开启异步功能 /** * @author fengzp * @date 17/5/8 * @email f ...

  4. postgresql-脏页和缓存失效

    脏页和缓存失效 https://www.cnblogs.com/flying-tiger/p/7885478.html Dirty pages and cache invalidation 我们一直在 ...

  5. elasticsearch5.6.3插件部署

    需要注意的是,5.x和2.x插件方面改动很大.参考:https://www.elastic.co/blog/running-site-plugins-with-elasticsearch-5-0.因为 ...

  6. xamarin android 实现二维码带logo生成效果

    MultiFormatWriter writer = new MultiFormatWriter(); Dictionary<EncodeHintType, object> hint = ...

  7. 自动化部署-从maven到shell脚本到jenkins

    Java代码自动部署 [ ①Java代码自动部署-总结简介] 代码部署是每一个软件开发项目组都会有的一个流程,也是从开发环节到发布功能必不可少的环节.对于Java开发者来说,Java代码的发布部署也是 ...

  8. #ifdef、#ifndef、#else、#endif执行条件编译

         我们开发的程序不只在pc端运行,也要在移动端运行.这时程序就要根据机器的环境来执行选择性的编译,如对PC端编译PC端的程序,对移动端编译移动端的程序,这里我们就可以用两组条件编译.     ...

  9. 全网最全的Windows下Anaconda2 / Anaconda3里正确下载安装用来定时任务apscheduler库(图文详解)

    不多说,直接上干货!  Anaconda2 里 PS C:\Anaconda2\Scripts> PS C:\Anaconda2\Scripts> pip.exe install apsc ...

  10. vue框架之自定义组件中使用v-model

    通常 vue在html常见表单空间支持v-model双向绑定例如 <input v-model="message" placeholder="edit me&quo ...