Spring的持久层封装

传统JDBC技术

下面的代码只是一个使用JDBC连接的示例,实际应用中不会这样用,一是代码繁琐,一是效率低。而Spring在持久层提供了更好的支持,对JDBC进行了良好的封装。

public class HelloWorld {
	Connection conn = null;
	Statement stml = null;
	{
		try {
			//获取数据连接
			Class.forName(com.microsoft.jdbc.sqlserver.SQLServerDriver);
			conn.DriverManager.getConnection(jdbc:microsoft:sqlserver:\\localhost:1433\stdb,admin,admin);
			//开始启动事务
			conn.setAutoCommit(false);
			stml = conn.createStatement();
			//执行相应操作
			stml.executeUpdate("insert into hello values(1,'gf','HelloWorld')");
			//执行成功则提交事务
			conn.commit();
		} catch (SQLException e) {
			if (conn != null) {
				try {
					//执行不成功,则回滚
					conn.rollback();
				} catch (SQLException ex) {
					System.out.println("数据连接有异常" + ex);
				}
			}
		} finally {
			//假如stmt不为空,则关闭 stmt
			if (stml != null) {
				try {
					stml.close();
				} catch (SQLException ex) {
					System.out.println("执行操作有异常" + ex);
				}
			} 
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException ex) {
					System.out.println("数据连接有异常" + ex);
				}
			}
		}
	}
}

通过XML实现DataSource(数据源)注入

Spring提供了3种XML实现数据源注入的方式:使用Spring自带的DriverManagerDataSource、使用DBCP连接池、使用Tomcat提供的JNDI。

(1)使用Spring自带的DriverManagerDataSource

使用DriverManagerDataSource在效率上和直接使用JDBC没有多大区别。配置文档和对于的java程序示例如下:

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<!--设定dataSource-->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<!--使用SQL Server数据集-->
		<property name="driverClassName">
			<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
		</property>
		<!--设定URL-->
		<property name="url">
			<value>jdbc:microsoft:sqlserver://localhost:1433/stdb</value>
		</property>
		<!--设定用户名-->
		<property name="name">
			<value>admin</value>
		</property>
		<!--设定密码-->
		<property name="msg">
			<value>admin</value>
		</property>
	</bean>
	<!--设定transactionManager-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	<!--示例中的一个DAO-->
	<bean id="helloDAO" class="com.gc.action.HelloDAO">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
	</bean>
</beans>
public class HelloDAO {
	private DataSource dataSource;
	private PlatformTransactionManager transactionManager;
	//通过依赖注入来完成管理
	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}
	public void setTransactionManager(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}
	//使用TransactionTemplate对create()方法进行事务管理
	public int create(String msg) {
		TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
		//调用TransactionTemplate的execute()方法,并覆写TransactionCallback类的doInTransaction()方法,在该方法里进行对数据库的新增操作
		Object result = transactionTemplate.execute(
			new TransactionCallback() {
			@Override
			public Object doInTransaction(TransactionStatus status) {
				JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
				Object resultObject = jdbcTemplate.update("INSERT INTO hello VALUES(1,'gf','HelloWorld')");
				return resultObject;
			}
		});	
	}
}

(2)使用DBCP连接池

Spring提供了DBCP连接池的支持,可以直接在配置文档中配置DBCP数据库连接池。

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<!--设定dataSource-->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<!--使用SQL Server数据集-->
		<property name="driverClassName">
			<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
		</property>
		<!--设定URL-->
		<property name="url">
			<value>jdbc:microsoft:sqlserver://localhost:1433/stdb</value>
		</property>
		<!--设定用户名-->
		<property name="name">
			<value>admin</value>
		</property>
		<!--设定密码-->
		<property name="msg">
			<value>admin</value>
		</property>
	</bean>
	<!--设定transactionManager-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	<!--示例中的一个DAO-->
	<bean id="helloDAO" class="com.gc.action.HelloDAO">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
	</bean>
</beans>

(3)使用Tomcat提供的JNDI

与使用DBCP连接池相比,使用Spring来进行Web开发,更多的使用Web容器提供的数据库连接池功能。如使用Romcat容器,及Tomcat提供的JNDI的配置。

首先在Tomcat的server.xml中添加以下代码:

<Context path="/myApp" reloadable="true" docBase="D:\eclipse\workspace\myApp" workDir="D:\eclipse\workspace\myApp\work">
	<Resource name="jdbc/opendb" auth="Container" 
		type="javax.sql.DataSource" 
		factory="org.apache.tomcat.dbcp.BasicDataSourceFactory" 
		driverClassName="com.microsoft.jdbc.sqlserver.SQLServerDriver" 
		url="jdbc:microsoft:sqlserver://localhost:1433/stdb"
		<!--设定用户名-->
		name="admin"
		<!--设定密码-->
		msg="admin"
		<!--设定最大连接数-->
		maxActive="10000"
		<!--设定最大空闲时间-->
		maxIdle="10000"
		<!--设定最大等待时间-->
		maxWait="10000"
		removeAbandoned="true"
		removeAbandonedTimeout="10"
		logAbandoned="true"
	/>
</Context>	

Spring配置如下:

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<!--设定dataSource-->
	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiName">
			<value>jndi/opendb</value>
		</property>
	</bean>
	<!--设定transactionManager-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	<!--示例中的一个DAO-->
	<bean id="helloDAO" class="com.gc.action.HelloDAO">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
	</bean>
</beans>

使用JdbcTemplate访问数据

(1)Template模式简介

Template模式:就是在父类中定义一个操作中算法的骨架或者说操作顺序,而将一些步骤的具体实现延迟到子类中。这个模式可能是最简单的模式了。

(1)父类骨架代码

package com.gc.action;

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.support.DefaultTransactionDefinition;

public abstract class Transaction{
	//事务处理的骨架代码,指明事务处理的操作顺序
	public Object execute() throws TransactionException {
		this.transactionManager.getTransaction(this);
		Object result = null;
		try {
			
		} catch (Error err) {
			// Transactional code throw error -> rollback
			this.transactionManager.rollback(this);
			throw err;
		}
		this.transactionManager.commit(this);
		return result;
	}
	//负责传入具体的事务
	public abstract Object doInTransaction();
}

(2)子类具体要进行事务处理的代码

public class SubTransaction extends Transaction {
    //负责传入具体的事务
    public Object doInTransaction() {
        //具体对数据库进行增删改的代码
    }
}

(2)事务处理中的TransactionTemplate的实现方式

TransactionTemplate事务处理代码:

public class TransactionTemplate extends DefaultTransactionDefinition implements InitializingBean {
	private PlatformTransactionManager transactionManager = null;
	//通过依赖注入
	public TransactionTemplate(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}
	public PlatformTransactionManager getTransactionManager() {
		return transactionManager;
	}
	public void setTransactionManager(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}
	//执行完毕后调用
	public void afterPropertiesSet() {
		if (this.transactionManager == null) {
			throw new IllegalAnnotationException("transactionManager is required");
		}
	}
	//进行事务处理的骨架,指明了事务处理的顺序
	public Object execute(TransactionCallback action) throws TransactionException {
		TransactionStatus status = this.transactionManager.getTransaction(this);
		Object result = null;
		try {
			//执行具体的方法
			result = action.doInTransaction(status);
		} catch (RuntimeException ex) {
			// Transactional code threw application exception -> roolback
			rollbackOnException(status,ex);
			throw ex;
		} catch (Error err) {
			// Transactional code threw error -> roolback
			rollbackOnException(status,err);
			throw err;
		}
		this.transactionManager.commit(status);
		return result;
	}
	//如果有异常就rollback
	private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException{
		try {
			this.transactionManager.rollback(status);
		} catch (RuntimeException ex2) {
			throw ex2;
		} catch (Error err) {
			throw err;
		}		
	}
}

这里的TransactionTemplate没有抽象类,在它的execute()方法里定义事务处理的骨架代码。但是execute()方法里的TransactionCallback参数却是个接口,在这个接口中定义了doInTransaction()方法。

public interface TransactionCallback {
    Object doInTransaction(TransactionStatus status);
}

只要实现这个接口,并在doInTransaction()方法里编写具体要进行事务处理的代码就可以了。

public class HelloDAO {
	private DataSource dataSource;
	private PlatformTransactionManager transactionManager;
	//通过依赖注入来完成管理
	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}
	public void setTransactionManager(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}
	//使用TransactionTemplate对create()方法进行事务管理
	public int create(String msg) {
		TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
		//调用TransactionTemplate的execute()方法,并覆写TransactionCallback类的doInTransaction()方法,在该方法里进行对数据库的新增操作
		Object result = transactionTemplate.execute(
			new TransactionCallback() {
			@Override
			public Object doInTransaction(TransactionStatus status) {
				JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
				Object resultObject = jdbcTemplate.update("INSERT INTO hello VALUES(1,'gf','HelloWorld')");
				return resultObject;
			}
		});	
	}
}

(3)JdbcTemplate的实现方式

JdbaTemplate封装了传统JDBC的功能也实现了Template模式。但与TransactionTemplate有些不同。

import jdk.nashorn.internal.runtime.Context.ThrowErrorManager;

public class JdbcTemplate extends JdbcAccessor implements JdbcOperations{
	......
	//使用回调方法
	public Object execute(ConnectionCallback action) throws DataAccessException {
		Connection con = DataSourceUtils.getConnection(getDataSource());
		try {
			Connection conToUse = con;
			if (this.nativeJdbcExtractor != null) {
				//Extract native JDBC Connection, castable t OracleConnection or the like.
				conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
			}
			else {
				//创建一个连接代理
				conToUse = createConnectionProxy(con);
			}
			return action.doInConnection(conToUse);
		} catch (SQLException ex) {
			// 释放连接
			DataSourceUtils.releaseConnection(con, getDataSource());
			con = null;
			throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex);
		} finally {
			DataSourceUtils.releaseConnection(con, getDataSource());
		}
	}
	//使用回调方法
	public Object execute(StatementCallback action) throws DataAccessException {
		Connection con = DataSourceUtils.getConnection(getDataSource());
		Statement stml = null;
		try {
			Connection conToUse = con;
			if (this.nativeJdbcExtractor != null && this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {
				//Extract native JDBC Connection, castable t OracleConnection or the like.
				conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
			}
			//创建Statement
			stml = conToUse.createStatement();
			applyStatementSetting(stml);
			Statement stmlToUse = stml;
			if (this.nativeJdbcExtractor != null) {
				stmlToUse = this.nativeJdbcExtractor.getNativeStatement(stml);
			}
			//初始化Statement
			Object result = action.doInStatement(stmlToUse);
			SQLWarning warning = stml.getWarnings();
			throwExceptionOnWarningIfNotIgnoringWarnings(warning);
			return result;
		} catch (SQLException ex) {
			// 释放连接
			DataSourceUtils.releaseConnection(con, getDataSource());
			con = null;
			throw getExceptionTranslator().translate("ConnectionCallback", getSql(action), ex);
		} finally {
			DataSourceUtils.releaseConnection(con, getDataSource());
		}
	}
	......
}

从上面JdbaTemplate的部分代码可以看出,JdbaTemplate与TransactionTemplate类似,都有execute()方法,并且execute()方法是一个接口。但是JdbaTemplate不需要在代码中使用回调方法,可以只是把SQL语句传入,直接执行。当然,也可以使用回调方法。

JdbaTemplate的使用:

(1)首先编写配置文档,然后通过程序使用JdbaTemplate,并于事务处理结合在一起。

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<!--设定dataSource-->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<!--使用SQL Server数据集-->
		<property name="driverClassName">
			<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
		</property>
		<!--设定URL-->
		<property name="url">
			<value>jdbc:microsoft:sqlserver://localhost:1433/stdb</value>
		</property>
		<!--设定用户名-->
		<property name="name">
			<value>admin</value>
		</property>
		<!--设定密码-->
		<property name="msg">
			<value>admin</value>
		</property>
	</bean>
	<!--设定transactionManager-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	<!--示例中的一个DAO-->
	<bean id="helloDAO" class="com.gc.action.HelloDAO">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
	</bean>
</beans>
public class HelloDAO {
	private DataSource dataSource;
	private PlatformTransactionManager transactionManager;
	//通过依赖注入来完成管理
	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}
	public void setTransactionManager(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}
	//使用JdbcTemplate
	public void create(String msg) {
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();//默认事务定义
		TransactionStatus status = transactionManager.getTransaction(def);//声明事务开始
		try {
			//使用JdbcTemplate往数据库里新增数据
			JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
			jdbcTemplate.update("INSERT INTO hello VALUES(1,'gf','HelloWorld')");
		} catch (DataAccessException ex) {
			// 也可以执行status.setRollbackOnly();
			transactionManager.rollback(status);
			throw ex;
		} finally {
			transactionManager.commit(status);
		}
	}
}

把配置文档中定义的dataSource通过JdbcTemplate的构造方法进行注入,然后直接执行JdbcTemplate的update()方法即可实现对数据库的操作。需要两行代码实现对数据库的操作。

(2)还可以把配置文档中定义的dataSource通过JdbcTemplate的构造方法进行注入也省略掉,直接在配置文档中配置,并使JdbcTemplate依赖于dataSource。这样只需要一行代码就可以实现对数据库的操作。

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<!--设定dataSource-->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<!--使用SQL Server数据集-->
		<property name="driverClassName">
			<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
		</property>
		<!--设定URL-->
		<property name="url">
			<value>jdbc:microsoft:sqlserver://localhost:1433/stdb</value>
		</property>
		<!--设定用户名-->
		<property name="name">
			<value>admin</value>
		</property>
		<!--设定密码-->
		<property name="msg">
			<value>admin</value>
		</property>
	</bean>
	<!--设定transactionManager-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	<!--设定jdbcTemplate-->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	<!--示例中的一个DAO-->
	<bean id="helloDAO" class="com.gc.action.HelloDAO">
		<!--依赖注入jdbcTemplate-->
		<property name="jdbcTemplate">
			<ref bean="jdbcTemplate"/>
		</property>
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
	</bean>
</beans>
public class HelloDAO {
	private JdbcTemplate jdbcTemplate;
	private PlatformTransactionManager transactionManager;
	//通过依赖注入来完成管理
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	public void setTransactionManager(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}
	//使用JdbcTemplate
	public void create(String msg) {
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();//默认事务定义
		TransactionStatus status = transactionManager.getTransaction(def);//声明事务开始
		try {
			//使用JdbcTemplate往数据库里新增数据
			jdbcTemplate.update("INSERT INTO hello VALUES(1,'gf','HelloWorld')");
		} catch (DataAccessException ex) {
			// 也可以执行status.setRollbackOnly();
			transactionManager.rollback(status);
			throw ex;
		} finally {
			transactionManager.commit(status);
		}
	}
}

(3)当然,既然构造方法的数据注入可以通过修改配置文件实现,那么要执行的SQL语句当然也可以通过配置文档进行配置,这样如果需要修改SQL语句,就不需要改变代码,只需要修改配置文档就可以了。

<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<!--设定dataSource-->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<!--使用SQL Server数据集-->
		<property name="driverClassName">
			<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
		</property>
		<!--设定URL-->
		<property name="url">
			<value>jdbc:microsoft:sqlserver://localhost:1433/stdb</value>
		</property>
		<!--设定用户名-->
		<property name="name">
			<value>admin</value>
		</property>
		<!--设定密码-->
		<property name="msg">
			<value>admin</value>
		</property>
	</bean>
	<!--设定transactionManager-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	<!--设定jdbcTemplate-->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	<!--示例中的一个DAO-->
	<bean id="helloDAO" class="com.gc.action.HelloDAO">
		<!--依赖注入jdbcTemplate-->
		<property name="jdbcTemplate">
			<ref bean="jdbcTemplate"/>
		</property>
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
		<property name="sql">
			<value>INSERT INTO hello VALUES(1,'gf','HelloWorld')</value>
		</property>
	</bean>
</beans>
public class HelloDAO {
	private JdbcTemplate jdbcTemplate;
	private PlatformTransactionManager transactionManager;
	private String sql;
	//通过依赖注入来完成管理
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	public void setTransactionManager(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}	
	public void setSql(String sql) {
		this.sql = sql;
	}
	//使用JdbcTemplate
	public void create(String msg) {
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();//默认事务定义
		TransactionStatus status = transactionManager.getTransaction(def);//声明事务开始
		try {
			//使用JdbcTemplate往数据库里新增数据
			jdbcTemplate.update(this.sql);
		} catch (DataAccessException ex) {
			// 也可以执行status.setRollbackOnly();
			transactionManager.rollback(status);
			throw ex;
		} finally {
			transactionManager.commit(status);
		}
	}
}

以上三种方法,代码量逐渐减少,并且都通过依赖注入实现。

(4)使用JdbaTemplate查询数据库

JdbaTemplate提供了很多用来查询数据库的方法:queryForMap()、queryForLong()、queryForInt()、queryForList()等。

List rows = jdbcTemplate.queryForList("select * from hello");
Iterator it = rows.iterator();
//通过Iterator获取list的值
while(it.hasNext()){
    Map map = (Map)it.next();
    String id = map.get("id");
    String name = map.get("name");
    String mag = map.get("mag");
}


int count = jdbcTemplate.queryForInt("select count(*) from hello");

(5)使用JdbaTemplate更改数据库

JdbcTemplate中的update()方法使进行数据库更爱的常用方式。

jdbcTemplate.update("insert into hello values(1,'gf','HelloWorld')");

jdbcTemplate.update("insert into hello values(?,?,?,)",new Object[]{1,'gf','HelloWorld'});

jdbcTemplate.update("insert into hello values(?,?,?,)",
                        new PreparedStatementSetter(){
                            public void setValues(PreparedStatement ps) throws SQLException {
                                ps.setInt(1,1);
                                ps.setInt(2,'gf');
                                ps.setInt(3,'HelloWorld');
                            }
                        }
                    );

jdbcTemplate.update("update hello set name='gf',msg='HelloWorld' where id=1");

jdbcTemplate.update("update hello set name=?,msg=? where id=?",new Object[]{'gf','HelloWorld',1});

使用ORM工具访问数据

(1)ORM简述

ORM(Object-Relational Mapping):对象关系映射。

因为开发人员使用的技术是面向对象技术,而使用的数据库却是关系型数据库。使用ORM,通过在对象和关系型之间建立起一座桥梁。Hibernate、iBatis就是这样的ORM工具。

ORM包括以下四个部分:

  • 一个对持久类对象进行CRUD操作的API。
  • 一个语言或API用来规定与类和类属性相关的查询。
  • 一个规定mapping metadata的工具。
  • 一种技术可以让ORM的实现同事务对象一起进行dirty checking,lazy association fetching以及其他的优化操作。

ORM模型的简单性简化了数据库查询过程。使用ORM查询工具,用户可以访问期望数据,而不必理解数据库的底层结构。

(2)使用Hibernate

Hibernate主要应用在持久层方面。

Spring与Hibernate结合在一起:

  • 加入Hibernate后的Spring的配置文档
  • Hibernate的配置文件Hello.hbm.xml
  • 存放数据的类Hello
  • HelloDAO的编写
<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<!--设定dataSource-->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<!--使用SQL Server数据集-->
		<property name="driverClassName">
			<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
		</property>
		<!--设定URL-->
		<property name="url">
			<value>jdbc:microsoft:sqlserver://localhost:1433/stdb</value>
		</property>
		<!--设定用户名-->
		<property name="name">
			<value>admin</value>
		</property>
		<!--设定密码-->
		<property name="msg">
			<value>admin</value>
		</property>
	</bean>
	<!--使用Hibernate的sessionFactory-->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
		<property name="dataSource">
			<ref local="dataSource"/>
		</property>
		<property name="mappingResources">
			<list>
				<value>com/gc/gction/Hello.hbm.xml</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<!--设定方言-->
				<prop key="hibernate.dialect">
					net.sf.hibernate.dialect.SQLServerDialect
				</prop>
				<!--是否显示sql-->
				<prop key="hibernate.show_sql">
					true
				</prop>
			</props>
		</property>
	</bean>
	<!--设定transactionManager-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="sessionFactory">
			<ref bean="sessionFactory"/>
		</property>
	</bean>
	<!--示例中的一个DAO-->
	<bean id="helloDAO" class="com.gc.action.HelloDAO">
		<!--依赖注入jdbcTemplate-->
		<property name="sessionFactory">
			<ref bean="sessionFactory"/>
		</property>
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
	</bean>
</beans>
<!--Hello.hbm.xml-->
<hibernate-mapping>
<class name="com.gc.action.Hello" table="hello" dynamic-update="false" dynamic-insert="false">
<id name="id" column="id" type="java.lang.Integer"/>
<property name="name"
type="java.lang.String"
update="true"
insert="true"
access="property"
<!--栏位名称为msg-->
column="msg"
<!--字段长度为50-->
length="50"/>
<property name="msg"
type="java.lang.String"
update="true"
insert="true"
access="property"
<!--栏位名称为name-->
column="name"
<!--字段长度为50-->
length="50"/>
</class>
</hibernate-mapping>
/**
* @hibernate.class table="hello"
*/
public class Hello {
    public Integer id;
    public String name;
    public String msg;
    /**
    * @hibernate.id
    * column="id"
    * type="java.lang.Integer"
    */
    public Integer getID() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    /**
    * @hibernate.property column="msg" length="50"
    */
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    /**
    * @hibernate.property column="name" length="50"
    */
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

在HelloDAO中使用SessionFactory,并和事务处理结合。

public class HelloDAO {
	private SessionFactory sessionFactory;
	private PlatformTransactionManager transactionManager;
	private String sql;
	//通过依赖注入来完成管理
	public void setSessionFactory(DataSource sessionFactory) {
		this.sessionFactory = sessionFactory;
	}	
	public void setTransactionManager(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}	
	//使用HibernateTemplate
	public void create(String msg) {
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();//默认事务定义
		TransactionStatus status = transactionManager.getTransaction(def);//声明事务开始
		try {
			HibernateTemplate hibernateTemplate = new HibernateTemplate(sessionFactory);
			//定义一个Hello
			Hello hello = new Hello();
			hello.setId(1);
			hello.setName("gf");
			hello.setMsg("HelloWorld");
			//保存或更新hello
			hibernateTemplate.saveOrUpdate(hello);
		} catch (DataAccessException ex) {
			// 也可以执行status.setRollbackOnly();
			transactionManager.rollback(status);
			throw ex;
		} finally {
			transactionManager.commit(status);
		}
	}
}

(3)使用iBatis

iBatis主要应用在持久层方面。

Spring与Hibernate结合在一起:

  • 加入iBatis后的Spring的配置文档
  • iBatis的配置文件sqlMapConfig.xml
  • 存放数据的类Hello
  • HelloDAO的编写
<?xml version="1.0" encoding="UTF8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<!--设定dataSource-->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<!--使用SQL Server数据集-->
		<property name="driverClassName">
			<value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>
		</property>
		<!--设定URL-->
		<property name="url">
			<value>jdbc:microsoft:sqlserver://localhost:1433/stdb</value>
		</property>
		<!--设定用户名-->
		<property name="name">
			<value>admin</value>
		</property>
		<!--设定密码-->
		<property name="msg">
			<value>admin</value>
		</property>
	</bean>
	<!--使用iBatis-->
	<bean id="sqlMap" class="org.springframework.orm.iBatis.SqlMapClientFactoryBean">
		<property name="configLocation">
			<value>WEB-INF/sqlMapConfig.xml</value>
		</property>
	</bean>
	<!--设定transactionManager-->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
	<!--示例中的一个DAO-->
	<bean id="helloDAO" class="com.gc.action.HelloDAO">
		<!--依赖注入jdbcTemplate-->
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
		<property name="sqlMap">
			<ref bean="sqlMap"/>
		</property>
	</bean>
</beans>
<!--sqlMapConfig.xml-->
<sqlMapConfig>
    <sqlMap resource="com/gc/action/Hello.xml"/>
</sqlMapConfig>
<!--Hello.xml-->
<sqlMap namespace="Hello">
    <typeAlias alias="hello" type="com.gc.action.Hello" />
    <insert id="insertHello" parameterClass="hello">
        insert into hello (id,name,msg) values(#id#,#name#,#msg#)
    </insert>
</sqlMap>
public class Hello {
    public Integer id;
    public String name;
    public String msg;
   
    public Integer getID() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
   
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//HelloDAO.java
public class HelloDAO extends SqlMapClientDaoSupport {
	private PlatformTransactionManager transactionManager;
	//通过依赖注入来完成管理
	public void setTransactionManager(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}	
	//使用getSqlMapClientTemplate
	public void create(String msg) {
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();//默认事务定义
		TransactionStatus status = transactionManager.getTransaction(def);//声明事务开始
		try {
			//定义一个Hello
			Hello hello = new Hello();
			hello.setId(1);
			hello.setName("gf");
			hello.setMsg("HelloWorld");
			//保存或更新hello
			getSqlMapClientTemplate().update("insertHello",hello);
		} catch (DataAccessException ex) {
			// 也可以执行status.setRollbackOnly();
			transactionManager.rollback(status);
			throw ex;
		} finally {
			transactionManager.commit(status);
		}
	}
}

 

发布了72 篇原创文章 · 获赞 38 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/u012839256/article/details/105669651