- 浏览: 101697 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
liuyifan789:
synchronize对单个节点可以,但是多个节点比如stru ...
Java 并发 -
owen_liulei:
写的很好,学习了
Java 并发 -
aramxiao:
写得非常好,简单描述就能把最核心的思想写了出来,楼主真神人也, ...
Java 并发 -
champion2008:
好文章,简单易懂
Java 并发 -
jiashaoshan:
jiashaoshan 写道引用好
Concurrent包常用方法简介
http://hi.baidu.com/dapplehou/blog/item/6ba8034f5114e038aec3abdb.html
两、三年前说过要坚持写文剖析各种算法、面向对象、框架、架构及各种应用技术,然进展缓慢,一者力有不逮,二者工作变动,无暇它顾。如今咬牙还债,算给自己个交代。这次就从最常用的DAO开始吧, J2EE应用开发中,数据库的使用非常频繁,大多公司里所使用的Framework都有对数据库操作进行封装的被称为DAO层的部分。下面,我结合自己在不同时期所参与的项目,就各种DAO层的封装方式进行一下比照。 在execQuery(String sql)中,做了3件事: 省却了婆婆妈妈的RecordSet, Statement的声明和繁琐重复的异常捕获。把查询结果放进缓存,不用一直维持着数据库的连接,可以减少数据库的数据连接压力。 基本上式是直接使用hibernate进行DAO层操作,未对hibernate进行二次封装; 这段代码会读取hibernate配置文件(hibernate.cfg.xml ), hibernate配置文件中有数据库连接信息,对象与数据库之间的映射文件的地址; 其实就是hibernate的优缺点。这个大家可以参考已经非常丰富的hibernate 资料;从审美角度上看,hibernate使数据存取代码简洁、清晰。而简洁清晰的代码总是更容易使用。 在下一个紧接着的项目中,有的模块对hibernate又进行了一层简单的封装,这样做的目的是为了使之扩展性更强。但实际上这也同时使得代码复杂度增加。这中间的平衡取舍往往不单单是技术问题。 下面我们这里举两种封装例子。 从这个UML中,我们可以看出它的思路,就是尘归尘、土归土,就是user的业务处理归UserManager,user的数据处理归UserManagerDAO.两者互不干扰。假如现在需求有变,数据被要求存在文件里而非数据库中,要做哪些工作呢? 可以看出,已有代码中修改了2处。这正是简单工厂模式的特点。 它减少了Manager这一层,而让用户直接使用DAO.它使用的模式是工厂模式。假如需求也有变,要求把数据存进文件里而非数据库中,要做哪些工作呢? 我们可以看出,这里对已有代码修改了一处。大家都知道OCP原则,即对扩展开放,对修改关闭。其本质就是对于已经存在的代码尽量不去动就能实现新的功能(扩展),其完全实现必然伴随形成热插拔的能力。 这里,仍然对已有代码做了一处修改,必然还需要重新编译。如果把实例化的控制开关放进配置文件中又配置人员来设定,就可以不需要再修改代码再编译,则基本可以看做可热插拔了。 补充一点,所有项目的业务含义就不说了。因为那样做不好。 架构采用 struts+spring+ibatis 组合。 请求被Action接收后, Action–>Logic–>Dao–>Ibatis. 符号"–>"代表调用. 关键的地方在于,所有的调用都是通过Spring的依赖注入实现,而不用程序员去写被调用对象的创建代码(比如写一个工厂类用来创建对象)。省了好多事哦。 Struts是最著名的MVC Framework,它的实现实质就是用一个Servlet统一接收请求,然后根据配置文件分发给不同的action,程序员在action中再调用自己的逻辑模块,处理完后,struts又根据配置文件把结果转发到相应的页面。这就完成了MVC的一个全过程。它是这么著名,以至于到处都是它的资料。所以欲知其详,请google. Ibatis是半自动化数据封装方案。它的实现实质就是通过读取写在配置文件中的SQL语句自动生成数据对象. Spring则发展的最火,因为它的确最棒。但要说它的实现实质,则也是通过读取含有class信息的配置文件,动态的生成类对象。多个class的依赖关系也写在配置文件中,Spring读取依赖关系、进行对象的构造,这就是依赖注入。 捎带提一句,要感谢夏昕为Spring的普及所做的贡献。正是2004年夏昕的 Spring Guide加速了Spring在众多的程序员中的普及进程。 配置文件的例子如下: 这个配置文件中,Department类引用了User类(Spring会自动根据引用构建依赖关系,也可以手工指定依赖关系)。Spring读这些文件,然后通过反射就可以构造出user对象与Department对象。然后再在此基础上发展演化,变成了今天的Spring. 它的基本原理简单,但为什么这样的framework总是被老外开发出来呢?不是中国程序员笨,可能要从历史和大环境找原因吧。 不说闲话,回归正题。这个项目采用了struts+spring+ibatis做架构,我们就来看一下它的使用方式。 这里用一个简单过程来说明。比如用户输入用户名和密码进行Logon,系统校验用户名密码是不是正确。(这是个演示例子,所以后面的代码一切从简)。 用户点击登陆,请求被struts送到了Logonaction,如下: userHandle实例是通过容器(ApplicationContext)获取的,不需要自己写创建对象的代码了。容器实际上是通过读取配置文件加载UserHandle类的,而这个过程对于程序员是透明的。 然后我们再分析下面这一句: userHanle类的通常实现方法可能是这样, 然后就可以想象UserDAO里就是数据库连接,发送SQL的那一套。这样做,程序员就不得不写一个 DBOperator类,用来创建DAO. 而Spring就是用来解放这样的创建工作的,这样 DBOperator这样的类就没必要程序员劳神去写了,只需要这样做: Spring 会根据配置文件中的类的依赖关系,自动的把UserDAO对象注入到 UserHandle对象里,然后程序员去使用userDao就可以了。 既然是根据配置文件来注入的,那么配置文件是什么样子呢?如下: 从这个配置文件里我们可以看到它们的引用关系是:1–>2–>3–>4,即 UserHandle引用UserDAO, UserDAO引用 SqlMapClientFactoryBean, SqlMapClientFactoryBean引用 JndiObjectFactoryBean,JndiObjectFactoryBean负责根据jndiName获得 datasource. 通过这样层层引用的配置,spring就能自动生成对象,不但免了程序员手动写对象生成的代码,还很容易的把ibatis串连起来。 前面我们已经根据代码和配置文件知道了UserHandle是怎么引用和注入 UserDAO的方式,现在我们再看UserDAO是怎么引用 SqlMapClientFactoryBean 这个第三方类的. 根据UserHandle引用UserDAO的方式,我们也应该猜到UserDAO引用 SqlMapClientFactoryBean时应该大致是这样: 但实际上,第三方类已经把set get这样的方法封装好了,你只需要继承第三方类就可以了,如这样: 这样就不用手工写那些set get方法了。原理也不难理解,那些set 和 get方法无非被挪进了SqlMapClientDaoSupport这个Spring提供的第三方类里面而已,我们可以看它的源码片段: 果然看到了getSqlMapClient()和setSqlMapClient()方法。我们仍然根据 UserHandle和UserDAO的注入方式,可以知道UserHandle的属性userDao其实就是UserDAO类的实例注入。同样,配置文件中UserDAO的属性sqlMapClient 也应该是SqlMapClientFactoryBean类的实例注入才对。但 SqlMapClientFactoryBean并不是SqlMapClient类型,这怎么能注入呢? 这是因为Spring的机制的缘故。简单的说,如果一个bean实现了 FactoryBean接口,那么Spring就不会把该bean本身实例化并返回,而是返回该bean的getObject()返回的对象。这是Sprign的游戏规则。我们来看一眼 SqlMapClientFactoryBean的源码片段: Spring这种机制的官方说明: 到此为止,我们已经知道UserDAO与SqlMapClient的关系,接下来看如何使用IBatis Ibatis是半自动化数据对象封装方案。我们看userDao怎么使用Ibatis 结合者段代码以及前面的配置文件的第三段,相信你已经大体明白了Ibatis的使用。这里就做一简单描述。先重新看一下配置文件的第三段: 注意这里有一个sql-map-config.xml文件。这个文件的内容如下: 再看user.xml文件里是什么? 现在,结合UserDAO类,和三个xml文件,应该容易知道它的原理: 逻辑层调用userDAO,userDAO通过Spring的粘合会去调用 Ibatis,Ibatis读取sql-map-config.xml文件,然后顺藤摸瓜,再读取user.xml文件,从中找到id="userid"的map,传递userid 给#userid#,得到完整的sql,执行sql,返回结果。详细的Ibatis的使用请参考相关手册。 Spring DAO是Spring对JDBC的封装。主要利用Template模式实现。先看看它的用法: Template模式配合回调的使用是JdbcTemplate的主要实现方式,下面是它的源码片段: 不用回调,如果用顺调,会是怎样的? 以下是模拟代码: 这样做简单,但两个函数耦合强,execute方法的返回类型与参数都规定的太死,限制了execute方法的使用范围。比如,如下的代码就不容易去使用execute方法: 但如果是接口回调方式,则灵活得多 可以看出,下面的这个方法可满足不同的需要 而下面这种方法相对死板(但也简单了不少) 模板模式请参考:http://hi.baidu.com/dapplehou/blog/item/0830c3ce9ccd4a0f93457e6d.html 相信很容易明白Spring是如何把那些关闭连接的琐事用模板模式封装起来的。 无论由于性能原因对数据库拆分,还是本身就是分布式数据库,都涉及到对多个数据库的操作。这要求程序能动态定位所需数据库,实际上就是在多个数据源中动态定位一个。 可采用把定位库的策略封装进一个中间层来屏蔽程序对于多库的敏感。一般采用Proxy模式封装这种DB路由(即:定位)逻辑。Spring又显身手,它对多库也提供了方案: 相应的配置文件如下: 当然,也可以不集成 AbstractRoutingDataSource . 而是实现DataSource接口,代码片段如下: 实际上,AbstractRoutingDataSource 就是DataSource接口的一个实现,继承 AbstractRoutingDataSource,比自己实现DataSource要少很多工作量,因为 AbstractRoutingDataSource都帮你做了。AbstractRoutingDataSource内部的数据库路由原理和上面的代码一样。 时间有限,先写到这里吧。关于DAO还有太多的东西可以写,还有深的内容可以挖掘,这些内容完全可以写本大厚书。这里主要是从一个Framework的角度来分析了一下大致的用法和实现思路。 Author: Dapple HouTable of Contents
1 言前
2 项目1 (久远,尚无SSH流行)
2.1 使用方式
- String dataSourceName 数据源名称(JNDI).
- boolean autoReleaseConnection 是否自动释放链接.
- boolean useStoreProcedure 是否使用存储过程.UserDAO userDAO = new UserDAO(null,false,false);
List allUser = userDAO.getAllUser();
2.2 原理
DataSet ds = execQuery(querySQL);
2.4 优点
2.5 缺点
3 项目2
3.1 使用方式(步骤)
IndexDAO dao = new IndexDAO();
DataSet dataset=this.getDataSet(request);
dao.addData(dataset,user);
ds.set("userstatus", "0");
ds.tablename = "T_Pop_User";dboperator.insertData(ds);
3.2 原理
3.4 优点:
3.5 缺点
4 项目3(大约04年,hibernate)
4.1 使用方式
User user = new User();
user.setID(23);
user.setName("Dapple");
UserManager.updateUser(user);Session s = SessionManager.getSession();
s.update(buyer);
4.2 原理( session 的获取方式 )
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session s = sessionFactory.openSession();
4.4 优缺点
4.5 两个对hibernate使用的例子
5 项目4 (struts+spring+ibatis)
5.1 架构说明
<bean id="user" class="test.User">
<property name="name"><value>张三</value></property>
<property name="age"><value>20</value></property>
</bean>
<bean id="department" class="test.Department">
<property name="user"><ref bean="user"/></property>
</bean>
5.2 使用方式及其原理
protected ActionForward doExecute(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception{
String name = request.getParameter("name");
String password = request.getParameter("password");
ServletContext sc = request.getSession().getServletContext();
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(ServletContext sc);
UserHandle userHandle = (UserHandle)ctx.getBean("userhandle"); //获取userhanle实例
boolean isSuccess = userHandle.check(name,password);
if(isSuccess){
return mapping.findForward("success");
}else{
return mapping.findForward("failed");
}
}boolean isSuccess = userHandle.check(name,password);
class UserHandle{
public boolean check(String name,String password){
UserDAO userDao = DBOperator.getUserDAO(); //你自己的DB操作的封装类
return userDao.check(name,password);
}
}class UserHandle{
private UserDAO userDao;
public boolean check(String name,String password){
return userDao.check(name,password);
}
public void setUserDao(UserDAO userDao){
this.userDao = userDao;
}
public UserDAO getUserDao(){
return this.userDao;
}
}<beans>
<!--4-->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>efmweb</value></property>
</bean>
<!--3-->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean" >
<property name="configLocation"><value>WEB-INF/sql-map-config.xml</value></property>
<property name="dataSource"><ref local="dataSource"/></property>
</bean>
<!--2-->
<bean id="userdao" class="UserDAO">
<property name="sqlMapClient"><ref bean="sqlMapClient"/></property>
</bean>
<!--1-->
<bean id="userhandle" class="UserHandle">
<property name="userDao"><ref bean="userdao" /></property>
</bean>
</beans>
5.2.1 UserDAO的实现以及如何使用第三方SqlMapClient.
class UserDAO{
private SqlMapClientFactoryBean sqlMapClient;
public void setSqlMapClient(SqlMapClientFactoryBean sqlMapClient){
this.sqlMapClient = sqlMapClient;
}
public SqlMapClientFactoryBean getSqlMapClient(){
return this.sqlMapClient;
}
...;//你自己定义的其它业务相关userDao逻辑;
}class UserDAO extends SqlMapClientDaoSupport{
...;//你自己定义的其它业务相关userDao逻辑;
}public abstract class SqlMapClientDaoSupport extends DaoSupport {
private SqlMapClientTemplate sqlMapClientTemplate = new SqlMapClientTemplate();
private boolean externalTemplate = false;
/**
* Set the JDBC DataSource to be used by this DAO.
* Not required: The SqlMapClient might carry a shared DataSource.
* @see #setSqlMapClient
*/
public final void setDataSource(DataSource dataSource) {
if (!this.externalTemplate) {
this.sqlMapClientTemplate.setDataSource(dataSource);
}
}
/**
* Return the JDBC DataSource used by this DAO.
*/
public final DataSource getDataSource() {
return this.sqlMapClientTemplate.getDataSource();
}
/**
* Set the iBATIS Database Layer SqlMapClient to work with.
* Either this or a "sqlMapClientTemplate" is required.
* @see #setSqlMapClientTemplate
*/
public final void setSqlMapClient(SqlMapClient sqlMapClient) {
if (!this.externalTemplate) {
this.sqlMapClientTemplate.setSqlMapClient(sqlMapClient);
}
}
/**
* Return the iBATIS Database Layer SqlMapClient that this template works with.
*/
public final SqlMapClient getSqlMapClient() {
return this.sqlMapClientTemplate.getSqlMapClient();
}
/**
* Return the SqlMapClientTemplate for this DAO,
* pre-initialized with the SqlMapClient or set explicitly.
*/
public final SqlMapClientTemplate getSqlMapClientTemplate() {
return this.sqlMapClientTemplate;
}
}
5.2.2 为什么SqlMapClientFactoryBean与SqlMapClient类型不同也可被注入?
public class SqlMapClientFactoryBean implements FactoryBean,InitializingBean {
private SqlMapClient sqlMapClient;
protected SqlMapClient buildSqlMapClient(Resource configLocation,Properties properties) throws IOException {
InputStream is = configLocation.getInputStream();
if (properties != null) {
if (buildSqlMapClientWithInputStreamAndPropertiesMethodAvailable) {
return SqlMapClientBuilder.buildSqlMapClient(is,properties);
} else {
return SqlMapClientBuilder.buildSqlMapClient(new InputStreamReader(is), properties);
}
} else {
if (buildSqlMapClientWithInputStreamMethodAvailable) {
return SqlMapClientBuilder.buildSqlMapClient(is);
} else {
return SqlMapClientBuilder.buildSqlMapClient(new InputStreamReader(is));
}
}
}
//这里就是返回的、并会被注入到其它类里的对象
public Object getObject() {
return this.sqlMapClient;
}
}public interface FactoryBean
Interface to be implemented by objects used within a BeanFactory which are themselves factories. If a bean implements
this interface, it is used as a factory for an object to expose, not directly as a bean instance that will be exposed
itself.
NB: A bean that implements this interface cannot be used as a normal bean. A FactoryBean is defined in a bean style, but
the object exposed for bean references (getObject() is always the object that it creates.
FactoryBeans can support singletons and prototypes, and can either create objects lazily on demand or eagerly on
startup. The SmartFactoryBean interface allows for exposing more fine-grained behavioral metadata.
This interface is heavily used within the framework itself, for example for the AOP ProxyFactoryBean or the
JndiObjectFactoryBean. It can be used for application components as well; however, this is not common outside of
infrastructure code.
NOTE: FactoryBean objects participate in the containing BeanFactory's synchronization of bean creation. There is usually
no need for internal synchronization other than for purposes of lazy initialization within the FactoryBean itself (or
the like).
Since:
08.03.2003
Author:
Rod Johnson, Juergen Hoeller
See Also:
BeanFactory, ProxyFactoryBean, JndiObjectFactoryBean
5.2.3 如何使用IBatis
class UserDAO{
private SqlMapClientFactoryBean sqlMapClient;
public void setSqlMapClient(SqlMapClientFactoryBean sqlMapClient){
this.sqlMapClient = sqlMapClient;
}
public SqlMapClientFactoryBean getSqlMapClient(){
return this.sqlMapClient;
}
//这里是使用Ibatis的地方
public User getUser(String userid) {
return super.getSqlMapClientTemplate().queryForList("userid",
userid);
}
}<!--3-->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean" >
<property name="configLocation"><value>WEB-INF/sql-map-config.xml</value></property>
<property name="dataSource"><ref local="dataSource"/></property>
</bean><sqlMapConfig>
<sqlMap resource="user.xml"/>
</sqlMapConfig><sqlMap>
<select id="userid" resultclass="UserDAO" parameterClass="java.lang.String">
select * from user where userid=#userid#
</select>
</sqlMap>
6 Spring DAO
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update("Update user set name='Jeff' where id=10");public int update(final String sql) throws DataAccessException {
Assert.notNull(sql, "SQL must not be null");
if (logger.isDebugEnabled()) {
logger.debug("Executing SQL update [" + sql + "]");
}
class UpdateStatementCallback implements StatementCallback,
SqlProvider {
public Object doInStatement(Statement stmt) //<------- 这个函数将被下面的方法回调
throws SQLException {
int rows = stmt.executeUpdate(sql);
if (logger.isDebugEnabled()) {
logger.debug("SQL update affected " + rows
+ " rows");
}
return new Integer(rows);
}
public String getSql() {
return sql;
}
}
return ((Integer) execute(new UpdateStatementCallback()))
.intValue();
}
public Object execute(StatementCallback action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(getDataSource());
Statement stmt = null;
try {
Connection conToUse = con;
if (this .nativeJdbcExtractor != null
&& this .nativeJdbcExtractor
.isNativeConnectionNecessaryForNativeStatements()) {
conToUse = this .nativeJdbcExtractor
.getNativeConnection(con);
}
stmt = conToUse.createStatement();
applyStatementSettings(stmt);
Statement stmtToUse = stmt;
if (this .nativeJdbcExtractor != null) {
stmtToUse = this .nativeJdbcExtractor
.getNativeStatement(stmt);
}
Object result = action.doInStatement(stmtToUse); //<------- 这里是回调的地方
handleWarnings(stmt.getWarnings());
return result;
} catch (SQLException ex) {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
JdbcUtils.closeStatement(stmt);
stmt = null;
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw getExceptionTranslator().translate(
"StatementCallback", getSql(action), ex);
} finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}public int update(final String sql) throws DataAccessException {
return execute(sql);
}
public int execute(String sql) throws DataAccessException {
Connection con = DataSourceUtils.getConnection();
Statement stmt = null;
stmt = con.createStatement();
int rows = stmt.executeUpdate(sql);
return rows;
//数据库连接关闭等代码略
}public User getUser(int id){
//无法使用int execute(String sql) 函数,因为它只返回一个int,不是想要的。
}public User getUser(int id) throws DataAccessException {
class UpdateStatementCallback implements StatementCallback {
public Object doInStatement(Statement stmt) //<------- 这个函数将被下面的方法回调
throws SQLException {
String sql = "select * from User where id ="+id;
ResultSet rs = stmt.executeUpdate(sql);
//下面略的部分是把rs取回的数据封装进User对象里。
//...略;
User user = getUser(rs);
return user;
}
}
return execute(new UpdateStatementCallback());
}public Object execute(StatementCallback action) throws DataAccessException
public int execute(String sql) throws DataAccessException
7 多库/多数据源
public class DynamicDataSource extends AbstractRoutingDataSource {//1. 继承AbstractRoutingDataSource
static Logger log = Logger.getLogger("DynamicDataSource");
protected Object determineCurrentLookupKey() {
...................; //2. 你的路由逻辑
return dataSourceId; //3. 返回你要使用的datasourceId
}
}<bean id="dataSource0" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>db1</value></property>
</bean>
<bean id="dataSource1" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>db1</value></property>
</bean>
<bean id="dataSource2" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>db1</value></property>
</bean>
<bean id="dataSource" class="xxx.xxx.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.Integer">
<entry key="0" value-ref="dataSource0"/>
<entry key="1" value-ref="dataSource1"/>
<entry key="2" value-ref="dataSource2"/>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSource0"/>
</bean>
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:com/bitfone/smartdm/dao/sqlmap/sql-map-config.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="UserInfoDAO" class="com.bitfone.smartdm.dao.impl.UserInfoDAO">
<property name="sqlMapClient" ref="sqlMapClient"/>
</bean>public class DynamicDataSource implements DataSource{
private static String dsDefault;
private Map dataSources;
public void setDsDefault(String dsDefault)
{
this.dsDefault = dsDefault;
}
public Connection getConnection() throws SQLException
{
DataSource targetDS = getDataSource();
return targetDS.getConnection();
}
public DataSource getDataSource()
{
..........
..........//你的路由逻辑
String dbName = ?;
DataSource ds = (DataSource)dataSources.get(dbName);
return ds;
}
......
}
8 结束
相关推荐
它通常发生在数据访问层代码中,如DAO层或Repository层。 #### 原因分析 导致 `org.springframework.dao.InvalidDataAccessApiUsageException` 的主要原因是Spring事务管理器默认将事务设置为只读模式。这意味着,...
在Struts2 + Spring + Hibernate(简称S2SH)框架中,数据访问层(DAO层)通常与视图层(如JSP页面)进行解耦设计。这种设计模式有助于提高系统的可维护性和扩展性。但在某些情况下,开发者可能需要在JSP页面直接...
在Spring框架中,数据服务层(通常指DAO层)主要用于存放数据,即与数据库的交互。Spring提供了多种方式来实现这一功能,例如使用JDBC模板、JPA、Hibernate等技术。 #### 四、Spring与其他框架的集成 1. **Struts...
- **拓展生态体系**:为了适应不同的应用场景,Play Framework 将逐步丰富其插件生态系统,提供更多实用工具和服务。 - **社区支持与贡献**:通过积极维护开源社区,吸引更多开发者参与贡献,共同推动框架的进步与...
通过这样的实例,你可以了解到在C#中如何将一个具体的业务功能分解到三层架构的不同部分。这种结构化的设计方式使得代码更易于管理和维护,同时也提高了代码的复用性。在实际开发中,你可以根据项目规模和复杂度调整...
BLL调用DAO层来执行实际的数据操作,并且对UI层提供服务,起到业务流程控制的作用。 3. 数据访问层(DAL):DAL是与数据库交互的接口,处理SQL语句的执行,如查询、插入、更新和删除数据。在C#中,可能使用ADO.NET...
2. **Data Access/Integration**:这部分涉及数据访问和集成,如JDBC抽象层、ORM支持(Hibernate、JPA等)、O/R Mapping和DAO支持,以及对NoSQL数据库的支持。 3. **Web**:Spring的Web模块包括了MVC框架,它提供了...
这一层通常使用ADO.NET或Entity Framework等技术实现,将业务逻辑与数据库操作分离,降低了数据库变更对上层的影响。DAL通过接口或数据访问对象(DAO)暴露其服务,使得业务逻辑层(BLL)可以无需关心具体的数据库...
DAO(Data Access ...通过分析和实践这些示例,开发者不仅能掌握DAO模式在ASP.NET中的应用,还能提高在实际项目中处理数据库的能力。同时,学习注释良好的代码也是一种良好的编程习惯,有助于团队协作和代码维护。
Spring 框架是 Java 开发中的一个核心组件,它为构建可维护、模块化且松耦合的应用程序提供了一种强大的...通过分析和运行这些示例,你可以深入理解 Spring 如何在实际项目中发挥作用,从而提升你的 Java 开发技能。
Spring Framework 2是Java开发中的一个关键框架,它极大地简化了企业级应用的构建和管理。这个框架的核心特性包括依赖注入(Dependency Injection, DI)、面向切面编程(Aspect-Oriented Programming, AOP)以及丰富...
《Spring Framework 4.1.0.RELEASE:深入解析与源码分析》 Spring Framework作为Java开发中的核心框架,以其强大的功能和灵活的设计理念,深受广大开发者喜爱。本篇文章将聚焦于Spring Framework 4.1.0.RELEASE版本...
在ASP.NET中,数据访问通常使用ADO.NET或者Entity Framework,它们提供了与SQL Server等数据库的接口。在这个实例中,可能有一个或多个数据访问对象(DAO)或数据访问实体(DTO),用于封装数据库操作。 三层架构的...
本文将深入探讨Spring Framework 2.0.2的主要功能,并分析其依赖关系。 首先,让我们了解Spring的核心理念:依赖注入(Dependency Injection,简称DI)。在2.0.2版本中,DI机制得到了进一步强化,使得对象之间的...
通常,这样的工具会根据数据库模式生成对应的实体类、DAO层、Service层以及Controller层代码,使得开发者可以快速构建出完整的CRUD操作。 在压缩包文件名称列表中,我们看到"zj-smart-framework-master",这可能是...
3. 数据访问层:使用ADO.NET、Entity Framework或其他ORM(对象关系映射)框架生成数据库操作的类,如DbContext、Repository或DAO(数据访问对象)。 使用C#三层代码生成器的优势在于: - 提高开发效率:开发者...
这一层通常包含了数据访问对象(DAO)或实体框架(Entity Framework)等技术,用于封装对数据库的操作,提供数据的CRUD(创建、读取、更新、删除)功能。通过将数据访问逻辑集中管理,数据访问层能够简化数据库操作...
提供的MySchool项目源码是学习三层开发的良好实例,初学者可以通过阅读和分析代码了解如何在实际项目中划分和组织这些层。源码中的每个类和方法都可能对应着特定的职责,这有助于理解各层之间的协作机制。 6. 实践...
1. **DAO操作**:使用Spring的JdbcTemplate或HibernateTemplate进行数据库操作,理解Spring如何简化数据访问层的编写。 2. **事务管理**:通过实例了解如何利用@Transactional注解实现声明式事务。 3. **AOP应用**:...