标准的jdbc操作流程:
String Driver=com.microsoft.sqlserver.jdbc.SQLServerDriver";
String url=jdbc:sqlserver://localhost:1433;DatabaseName=dbname";
String user="sa";
String password="sa";Class.forName(driverClass);
Connection conn=DriverManager.getConnection(url,user,password);
Connection对象代表与数据库的连接
createStatement() //创建Statement对象
prepareStatement(String sql) //创建预处理语句
prepareCall(String sql) //来处理一个 SQL 存储过程调用语句
close() //关闭数据库连接
isClosed() //判断数据库连接是否超时或被显示关闭
setAutoCommit() //设置操作是否自动提交到数据库,默认为 true
commit() //提交所执行的SQL语句,在 setAutoCommit(false)之后才有效
rollback() //回滚所执行的SQL语句在 setAutoCommit(false) 之后才有效
getMetaData() //获取一个DatabaseMetaData对象,该对象包含了有关数据库的基本信息
Hibernate的封装:
org.hibernate.jdbc.ConnectionManager
public Connection getConnection() throws HibernateException {
.....
openConnection();
.....
}
private void openConnection() throws HibernateException{
......
connection = factory.getConnectionProvider().getConnection();
......
}
ConnectionProvider是 factory.getConnectionProvider()返回的对象的接口.
且看有哪些对象实现了这个接口?
挑其中一个来看-DriverManagerConnectionProvider,我们是否看到了很多熟悉的变量名?比如driverClass,autocommit,isolation,url
public void configure(Properties props) throws HibernateException {
String driverClass = props.getProperty(Environment.DRIVER);
autocommit = PropertiesHelper.getBoolean(Environment.AUTOCOMMIT, props);
isolation = PropertiesHelper.getInteger(Environment.ISOLATION, props);
if (driverClass==null) {
log.warn("no JDBC Driver class was specified by property " + Environment.DRIVER);
}
else {
try {
// trying via forName() first to be as close to DriverManager's semantics
Class.forName(driverClass);
}
catch (ClassNotFoundException cnfe) {
try {
ReflectHelper.classForName(driverClass);
}
catch (ClassNotFoundException e) {
String msg = "JDBC Driver class not found: " + driverClass;
log.error( msg, e );
throw new HibernateException(msg, e);
}
}
}
url = props.getProperty( Environment.URL );
if ( url == null ) {
String msg = "JDBC URL was not specified by property " + Environment.URL;
log.error( msg );
throw new HibernateException( msg );
}
connectionProps = ConnectionProviderFactory.getConnectionProperties( props );
log.info( "using driver: " + driverClass + " at URL: " + url );
}
我们是否看到了熟悉的connection获取的代码.
public Connection getConnection() throws SQLException {
..............
Connection conn = DriverManager.getConnection(url, connectionProps);
...............
return conn;
}
继而Hibernate抽象出了一个对象 org.hibernate.jdbc.JDBCContext
它和ConnectionManager的关系是 has-a. 同时,他实现了ConnectionManager.Callback
在创建ConnectionManager的同时,将自身的引用传递给了ConnectionManager实例,注册了一个钩子.
public JDBCContext(Context owner, Connection connection, Interceptor interceptor) {
...................
this.connectionManager = new ConnectionManager(
owner.getFactory(),
this,
owner.getConnectionReleaseMode(),
connection,
interceptor
);
...................
}
同时,在JDBCContext中声明了一个接口
public static interface Context extends TransactionFactory.Context {
/**
* We cannot rely upon this method being called! It is only
* called if we are using Hibernate Transaction API.
*/
public void afterTransactionBegin(Transaction tx);
public void beforeTransactionCompletion(Transaction tx);
public void afterTransactionCompletion(boolean success, Transaction tx);
public ConnectionReleaseMode getConnectionReleaseMode();
public boolean isAutoCloseSessionEnabled();
}
再看看JDBCContext的构造函数中的Context owner,
意味着,JDBCContext是提供了一个钩子,看接口定义的行为来判断,应该是为事务前后的处理提供的钩子入口.
JDBCContext 会在哪里创建呢?
org.hibernate.impl.SessionImpl中会创建,可以看到SessionImpl将自身的引用注册到了JDBCContext实例中.
SessionImpl实现了Context接口.
this.jdbcContext = new JDBCContext( this, connection, interceptor );
那么Hibernate是如何来完成事务控制的呢?
我们来看一下传统的事务控制代码.
Connection.setAutoCommit(false)
Connection.commit();
如果出现错误就调用
Connection.rollback();
再来看看Hibernate如何封装JDBC事务控制的.
事务接口
org.hibernate.Transaction
实现这个接口的对象有:
我们来看看JDBCTransaction
public void begin() throws HibernateException {
.....................
try {
toggleAutoCommit = jdbcContext.connection().getAutoCommit();
if (toggleAutoCommit) {
log.debug("disabling autocommit");
jdbcContext.connection().setAutoCommit(false);
}
}
catch (SQLException e) {
.....................
}
.................
}
核心代码和传统JDBC方式一模一样.
在JDBCContext中有如下方法:
public Transaction getTransaction() throws HibernateException {
if (hibernateTransaction==null) {
hibernateTransaction = owner.getFactory().getSettings()
.getTransactionFactory()
.createTransaction( this, owner );
}
return hibernateTransaction;
}
这个owner就是我们刚才说到的SessionImpl-JDBCContext构造函数中的Context接口的实现.