asp.net和j2ee的三层结构代码比较
2007-05-31 00:47
477 查看
1 前言
j2ee曾提出多层结构的开发框架,但实际项目中三层结构仍旧是主流。一般划分为数据展现层、业务逻辑层、数据访问层。数据展现层只管数据的显示,完全不关心具体的业务逻辑;业务逻辑层负责业务逻辑处理,它位于数据展现层和数据访问层中间,其主要任务为调用数据访问层获取数据,以便交给展现层进行显示;数据访问层一般就负责访问数据库,如通过jdbc/odbc/ado.net等手段访问数据库。
日常的三层结构开发中,大部分精力耗费在CRUD(增删改查)操作上。笔者分别在j2ee和asp.net 2.0上进行了小试验,比较两者之间的开发特征。
2 j2ee和asp.net三层开发代码结构
2.1 asp.net 2.0平台
展现层:GridView / FormView / DetailView / DataList / Reapter, MasterPage以及自定义控件等asp服务器端控件对传统HTML标签进行了封装。
业务层:BLL(Business Login Layer),对CRUD操作进行封装,并采用ObjectDataStore封装要返回给展现层的数据对象。
数据访问层:DAL(Data Access Layer),采用ADO.net(SqlConnection或OracleConnection等)来访问数据库。
2.1.1 展现层代码
利用GridView,CRUD操作可以集中在一个asp页面中。EditItemTemplate对应修改;增加记录时,可以将输入表单显示到脚注FooterTemplate中;删除不需要界面;查询显示用ItemTemplate,这4个方面合成到一个TemplateField中,针对不同的操作显示相应的控件。
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblProductName" runat="Server"><%# Eval("ProductName") %></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtProductName" runat="Server" Text='<%# Bind("ProductName") %>'></asp:TextBox>
</EditItemTemplate>
<FooterTemplate>
<asp:Button ID="btnInsert" Text="新增" OnClick="btnInsert_Click" runat="server" />
<asp:Button ID="btnCancel" Text="取消" OnClick="btnCancel_Click" runat="server" />
<asp:TextBox ID="txtProductID" runat="Server" Text=''></asp:TextBox>
<asp:TextBox ID="txtProductName" runat="Server" Text=''></asp:TextBox>
</FooterTemplate>
</asp:TemplateField>
2.1.2 业务层代码
实现业务逻辑(比如参数值校验),并调用DAL对象提供的CRUD操作,比如GetProducts(),UpdateProduct(),DeleteProduct(), InsertProduct().
public SqlDataReader GetProducts();
public int UpdateProduct(int productID, string productName, double unitPrice, Int16 unitsInStock);
public int DeleteProduct(int productID);
public int InsertProduct(int ProductID,
string ProductName,
int SupplierID,
int CategoryID,
string QuantityPerUnit,
double UnitPrice,
int UnitsInStock,
int UnitsOnOrder,
int ReorderLevel,
int Discontinued);
当然还有另外一种asp.net接受的函数声明方法,是将增删改的参数统一改成一个Product对象。
public SqlDataReader GetProducts();
public int UpdateProduct(Product prod);
public int DeleteProduct(Product prod);
public int InsertProduct(Product Prod);
2.1.3 数据访问层
调用ADO.net访问数据库(利用SqlConnection, SqlCommand, SqlDataReader等对象),注意不同数据库Connection的写法有不同。比如OracleConnection的参数绑定上与SqlConnection有区别。
// 返回DataSet或DataReader或者泛型列表List<Product>
public SqlDataReader GetProducts()
{
SqlConnection conn = new SqlConnection(m_ConnStr);
string sql = "select * from CatProd";
SqlCommand cmd = new SqlCommand(sql, conn);
conn.Open();
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return reader;
}
public int UpdateProduct(int productID, string productName, double unitPrice, Int16 unitsInStock)
{
int cnt = 0;
SqlConnection conn = new SqlConnection(m_ConnStr);
string sql = @"update CatProd set ProductName = @ProductName, UnitPrice = @unitPrice, UnitsInStock = @unitsInStock
where ProductID = @ProductID";
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@ProductID", productID);
cmd.Parameters.AddWithValue("@ProductName", productName);
cmd.Parameters.AddWithValue("@unitPrice", unitPrice);
cmd.Parameters.AddWithValue("@unitsInStock", unitsInStock);
conn.Open();
cnt = cmd.ExecuteNonQuery();
conn.Close();
return cnt;
}
2.2 j2ee平台
展现层:struts框架显示数据。
业务层:Service/Manager等业务封装对象。(可选用Spring,EJB等框架)
数据访问层:DAO模式通过jdbc(或jdbc的轻量级封装工具Hibernate,ibatis,SpringJDBC等)访问底层数据库。
2.2.1 展现层代码
采用struts框架,MVC模式简化了展现层的代码,几乎完全消除了以往jsp代码中的嵌入式java代码。在jsp页面中采用了标签库
<%@taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
<%@taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
<%@taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>
一个典型的jsp列表页面(比如listbook.jsp书籍清单)为
<table align="left" border="1" width="70%">
<tr bgcolor="#COCOCO">
<td align="center">
<bean:message key="book.id" />
</td>
<td align="center">
<bean:message key="book.name" />
</td>
<td align="center">
<bean:message key="book.author" />
</td>
<td align="center">
<bean:message key="book.publish" />
</td>
<td align="center">
<bean:message key="book.price" />
</td>
<td align="center">
<bean:message key="book.operator" />
</td>
</tr>
<logic:iterate id="book" name="books" scope="session">
<tr>
<td width="10%">
<bean:write name="book" property="bookId" />
</td>
<td width="25%">
<bean:write name="book" property="bookName" />
</td>
<td width="10%">
<bean:write name="book" property="author" />
</td>
<td width="25%">
<bean:write name="book" property="publish" />
</td>
<td width="10">
<bean:write name="book" property="price" />
</td>
<td width="25%">
<a
href="operatorAction.do?operator=showModify&bookid=<bean:write name="book" property="bookId"/>">
<bean:message key="link.modify" /> </a>
<a
href="operatorAction.do?operator=showDelete&bookid=<bean:write name="book" property="bookId"/>">
<bean:message key="link.delete" /> </a>
</td>
<bean:define id="bookid" name="book" property="bookId" />
</tr>
</logic:iterate>
</table>
上述用bean:message,并将字符串保存到ApplicationResources.properties文件中,根据locale的不同,可以实现国际化的要求(比如一键切换中英文版本)
在action处理代码中,实现execute方法,调用业务逻辑层的代码,取得值对象(VO, Value Object)的列表,保存到jsp内建对象(如request或session)中后,进行页面跳转。
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
List books = null;
BookDAO jdbc = new BookJdbcDAO();
books = jdbc.findAllBooks();
// request.setAttribute("books", books);
request.getSession().setAttribute("books", books);
return mapping.findForward("success");
}
2.2.2 业务层代码
业务层常见的方式是定义Service或Manger的接口以及相关实现类,比如UserService(UserManager, IUserService)接口,并提供对应实现类UserServiceImpl(UserManagerImpl, UserService),一般这些实现类都是直接调用相应的DAO中的方法。
public class UserServiceImpl implements UserService {
private UserDAO userDAO = null;
public void setUserDAO(UserDAO dao) {
// TODO Auto-generated method stub
this.userDAO = dao;
}
public int insert(User user) {
// TODO Auto-generated method stub
return userDAO.insert(user);
}
public int update(User user) {
// TODO Auto-generated method stub
return userDAO.update(user);
}
public int delete(User user) {
// TODO Auto-generated method stub
return userDAO.delete(user);
}
public int[] batchInsert(List users) {
// TODO Auto-generated method stub
return userDAO.batchInsert(users);
}
public User findById(int id) {
// TODO Auto-generated method stub
return userDAO.findById(id);
}
public List findByName(String name) {
// TODO Auto-generated method stub
return userDAO.findByName(name);
}
}
2.2.3 数据访问层
具体访问数据库,提供CRUD的方法,一般可以借助于SpringJDBC,Hibernate / iBatis等工具来简化编写数据库访问的代码。下面给出以SpringJDBC为数据访问方式的代码。
public class UserDAOImpl implements UserDAO {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemp) {
this.jdbcTemplate = jdbcTemp;
}
public int insert(User user) {
String sql = "insert into user(id, name, password) values(null, ?, ?)";
Object[] values = new Object[] { user.getName(), user.getPassword() };
return jdbcTemplate.update(sql, values);
}
public int update(User user) {
String sql = "update user set name = ?, password = ? where id = ?";
Object[] values = new Object[] { user.getName(), user.getPassword(),
new Integer(user.getId()) };
return jdbcTemplate.update(sql, values);
}
public int[] batchInsert(final List users) {
String sql = "insert into user(id, name, password) values(null, ?, ?)";
BatchPreparedStatementSetter setter = new BatchPreparedStatementSetter() {
public int getBatchSize() {
return users.size();
}
public void setValues(PreparedStatement pstmt, int index)
throws SQLException {
User user = (User) users.get(index);
pstmt.setString(1, user.getName());
pstmt.setString(2, user.getPassword());
}
};
return jdbcTemplate.batchUpdate(sql, setter);
}
public int delete(User user) {
String sql = "delete from user where id = ?";
Object[] values = new Object[] { new Integer(user.getId()) };
return jdbcTemplate.update(sql, values);
}
public User findById(int id) {
String sql = "select * from user where id = ?";
Object[] values = new Object[] { new Integer(id) };
final User user = new User();
jdbcTemplate.query(sql, values, new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
}
});
return user;
}
public List findByName(String name) {
String sql = "select * from user where name = ?";
Object[] values = new Object[] { name };
//final List users = new ArrayList();
return (List) jdbcTemplate.query(sql, values, new ResultSetExtractor() {
public Object extractData(ResultSet rs) throws SQLException,
DataAccessException {
List users = new ArrayList();
while (rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
users.add(user);
}
return users;
}
});
//return users;
}
}
3 总结
3.1 粗浅的比较
在数据展现层方面,asp.net实现了代码和HTML标签元素的彻底分离(比如filename.aspx, filename.aspx.cs),通过回发(postback)对鼠标、键盘等事件进行处理。配套VS2005的可视化编辑功能,代码编写的工作量较小。而这方面J2EE平台上略嫌不足,Struts的配置以及jsp页面上的标签代码编写稍显繁琐(不知JSF对展现层的代码简化程度如何?)。
在业务逻辑方面,asp.net隔离为BLL层,编写业务逻辑控制的相关代码。在J2EE平台上,产生了各种业务逻辑层的开发框架,比如Spring的容器,管理各种业务逻辑对象的生命周期,使得程序员可以更加专注于业务逻辑,同时增加了代码注入和对象组装和灵活配置的能力(AOP,代码反转注入等)
在数据访问层,asp.net采用ADO.net的方式,对SQLServer支持很好,通过System.data.OracleClient亦对Oracle进行了支持。J2EE可以采用jdbc或各种jdbc的封装框架(SpringJdbc, Hibernate/iBatis等),可选择的范围很广,故可根据项目需要进行搭配。
两者之间的差别,很大程度上是由于一个是商业软件,一个是开源社区推动型的两大阵营的差异造成的。从asp.net的三层结构开发的设计思想来看,应该是吸取并借鉴了很多开源框架的优秀设计思想,但总体来说,开源社区更具有活力。
3.2 其它需考虑的问题
关于事务的处理:即将事务控制放在数据访问层还是业务逻辑层?取决于业务的复杂程度,若分布式跨越多个数据库,则在J2EE平台上用JTA,因为JDBC的事务控制局限于当前连接,而一个连接只属于一个数据库。
层之间的接口以及数据传输:ORM映射后,对象和关系(数据库表)建立起了对应关系,j2ee平台用值对象(VO, PO, javabean)来实现数据封装和层之间的传递,asp.net上通常用DataSet,当然也可以用值对象来传输。
如何基于项目需求来选择合适的开发框架:项目的规模,需求特征(如增删改操作和查询操作分别所占的比例),是否数据密集型(使用普通SQL语句或调用存储过程的决定),框架的开发成本和人力成本等各种因素的考虑。
j2ee曾提出多层结构的开发框架,但实际项目中三层结构仍旧是主流。一般划分为数据展现层、业务逻辑层、数据访问层。数据展现层只管数据的显示,完全不关心具体的业务逻辑;业务逻辑层负责业务逻辑处理,它位于数据展现层和数据访问层中间,其主要任务为调用数据访问层获取数据,以便交给展现层进行显示;数据访问层一般就负责访问数据库,如通过jdbc/odbc/ado.net等手段访问数据库。
日常的三层结构开发中,大部分精力耗费在CRUD(增删改查)操作上。笔者分别在j2ee和asp.net 2.0上进行了小试验,比较两者之间的开发特征。
2 j2ee和asp.net三层开发代码结构
2.1 asp.net 2.0平台
展现层:GridView / FormView / DetailView / DataList / Reapter, MasterPage以及自定义控件等asp服务器端控件对传统HTML标签进行了封装。
业务层:BLL(Business Login Layer),对CRUD操作进行封装,并采用ObjectDataStore封装要返回给展现层的数据对象。
数据访问层:DAL(Data Access Layer),采用ADO.net(SqlConnection或OracleConnection等)来访问数据库。
2.1.1 展现层代码
利用GridView,CRUD操作可以集中在一个asp页面中。EditItemTemplate对应修改;增加记录时,可以将输入表单显示到脚注FooterTemplate中;删除不需要界面;查询显示用ItemTemplate,这4个方面合成到一个TemplateField中,针对不同的操作显示相应的控件。
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="lblProductName" runat="Server"><%# Eval("ProductName") %></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtProductName" runat="Server" Text='<%# Bind("ProductName") %>'></asp:TextBox>
</EditItemTemplate>
<FooterTemplate>
<asp:Button ID="btnInsert" Text="新增" OnClick="btnInsert_Click" runat="server" />
<asp:Button ID="btnCancel" Text="取消" OnClick="btnCancel_Click" runat="server" />
<asp:TextBox ID="txtProductID" runat="Server" Text=''></asp:TextBox>
<asp:TextBox ID="txtProductName" runat="Server" Text=''></asp:TextBox>
</FooterTemplate>
</asp:TemplateField>
2.1.2 业务层代码
实现业务逻辑(比如参数值校验),并调用DAL对象提供的CRUD操作,比如GetProducts(),UpdateProduct(),DeleteProduct(), InsertProduct().
public SqlDataReader GetProducts();
public int UpdateProduct(int productID, string productName, double unitPrice, Int16 unitsInStock);
public int DeleteProduct(int productID);
public int InsertProduct(int ProductID,
string ProductName,
int SupplierID,
int CategoryID,
string QuantityPerUnit,
double UnitPrice,
int UnitsInStock,
int UnitsOnOrder,
int ReorderLevel,
int Discontinued);
当然还有另外一种asp.net接受的函数声明方法,是将增删改的参数统一改成一个Product对象。
public SqlDataReader GetProducts();
public int UpdateProduct(Product prod);
public int DeleteProduct(Product prod);
public int InsertProduct(Product Prod);
2.1.3 数据访问层
调用ADO.net访问数据库(利用SqlConnection, SqlCommand, SqlDataReader等对象),注意不同数据库Connection的写法有不同。比如OracleConnection的参数绑定上与SqlConnection有区别。
// 返回DataSet或DataReader或者泛型列表List<Product>
public SqlDataReader GetProducts()
{
SqlConnection conn = new SqlConnection(m_ConnStr);
string sql = "select * from CatProd";
SqlCommand cmd = new SqlCommand(sql, conn);
conn.Open();
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return reader;
}
public int UpdateProduct(int productID, string productName, double unitPrice, Int16 unitsInStock)
{
int cnt = 0;
SqlConnection conn = new SqlConnection(m_ConnStr);
string sql = @"update CatProd set ProductName = @ProductName, UnitPrice = @unitPrice, UnitsInStock = @unitsInStock
where ProductID = @ProductID";
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@ProductID", productID);
cmd.Parameters.AddWithValue("@ProductName", productName);
cmd.Parameters.AddWithValue("@unitPrice", unitPrice);
cmd.Parameters.AddWithValue("@unitsInStock", unitsInStock);
conn.Open();
cnt = cmd.ExecuteNonQuery();
conn.Close();
return cnt;
}
2.2 j2ee平台
展现层:struts框架显示数据。
业务层:Service/Manager等业务封装对象。(可选用Spring,EJB等框架)
数据访问层:DAO模式通过jdbc(或jdbc的轻量级封装工具Hibernate,ibatis,SpringJDBC等)访问底层数据库。
2.2.1 展现层代码
采用struts框架,MVC模式简化了展现层的代码,几乎完全消除了以往jsp代码中的嵌入式java代码。在jsp页面中采用了标签库
<%@taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
<%@taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
<%@taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>
一个典型的jsp列表页面(比如listbook.jsp书籍清单)为
<table align="left" border="1" width="70%">
<tr bgcolor="#COCOCO">
<td align="center">
<bean:message key="book.id" />
</td>
<td align="center">
<bean:message key="book.name" />
</td>
<td align="center">
<bean:message key="book.author" />
</td>
<td align="center">
<bean:message key="book.publish" />
</td>
<td align="center">
<bean:message key="book.price" />
</td>
<td align="center">
<bean:message key="book.operator" />
</td>
</tr>
<logic:iterate id="book" name="books" scope="session">
<tr>
<td width="10%">
<bean:write name="book" property="bookId" />
</td>
<td width="25%">
<bean:write name="book" property="bookName" />
</td>
<td width="10%">
<bean:write name="book" property="author" />
</td>
<td width="25%">
<bean:write name="book" property="publish" />
</td>
<td width="10">
<bean:write name="book" property="price" />
</td>
<td width="25%">
<a
href="operatorAction.do?operator=showModify&bookid=<bean:write name="book" property="bookId"/>">
<bean:message key="link.modify" /> </a>
<a
href="operatorAction.do?operator=showDelete&bookid=<bean:write name="book" property="bookId"/>">
<bean:message key="link.delete" /> </a>
</td>
<bean:define id="bookid" name="book" property="bookId" />
</tr>
</logic:iterate>
</table>
上述用bean:message,并将字符串保存到ApplicationResources.properties文件中,根据locale的不同,可以实现国际化的要求(比如一键切换中英文版本)
在action处理代码中,实现execute方法,调用业务逻辑层的代码,取得值对象(VO, Value Object)的列表,保存到jsp内建对象(如request或session)中后,进行页面跳转。
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
List books = null;
BookDAO jdbc = new BookJdbcDAO();
books = jdbc.findAllBooks();
// request.setAttribute("books", books);
request.getSession().setAttribute("books", books);
return mapping.findForward("success");
}
2.2.2 业务层代码
业务层常见的方式是定义Service或Manger的接口以及相关实现类,比如UserService(UserManager, IUserService)接口,并提供对应实现类UserServiceImpl(UserManagerImpl, UserService),一般这些实现类都是直接调用相应的DAO中的方法。
public class UserServiceImpl implements UserService {
private UserDAO userDAO = null;
public void setUserDAO(UserDAO dao) {
// TODO Auto-generated method stub
this.userDAO = dao;
}
public int insert(User user) {
// TODO Auto-generated method stub
return userDAO.insert(user);
}
public int update(User user) {
// TODO Auto-generated method stub
return userDAO.update(user);
}
public int delete(User user) {
// TODO Auto-generated method stub
return userDAO.delete(user);
}
public int[] batchInsert(List users) {
// TODO Auto-generated method stub
return userDAO.batchInsert(users);
}
public User findById(int id) {
// TODO Auto-generated method stub
return userDAO.findById(id);
}
public List findByName(String name) {
// TODO Auto-generated method stub
return userDAO.findByName(name);
}
}
2.2.3 数据访问层
具体访问数据库,提供CRUD的方法,一般可以借助于SpringJDBC,Hibernate / iBatis等工具来简化编写数据库访问的代码。下面给出以SpringJDBC为数据访问方式的代码。
public class UserDAOImpl implements UserDAO {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemp) {
this.jdbcTemplate = jdbcTemp;
}
public int insert(User user) {
String sql = "insert into user(id, name, password) values(null, ?, ?)";
Object[] values = new Object[] { user.getName(), user.getPassword() };
return jdbcTemplate.update(sql, values);
}
public int update(User user) {
String sql = "update user set name = ?, password = ? where id = ?";
Object[] values = new Object[] { user.getName(), user.getPassword(),
new Integer(user.getId()) };
return jdbcTemplate.update(sql, values);
}
public int[] batchInsert(final List users) {
String sql = "insert into user(id, name, password) values(null, ?, ?)";
BatchPreparedStatementSetter setter = new BatchPreparedStatementSetter() {
public int getBatchSize() {
return users.size();
}
public void setValues(PreparedStatement pstmt, int index)
throws SQLException {
User user = (User) users.get(index);
pstmt.setString(1, user.getName());
pstmt.setString(2, user.getPassword());
}
};
return jdbcTemplate.batchUpdate(sql, setter);
}
public int delete(User user) {
String sql = "delete from user where id = ?";
Object[] values = new Object[] { new Integer(user.getId()) };
return jdbcTemplate.update(sql, values);
}
public User findById(int id) {
String sql = "select * from user where id = ?";
Object[] values = new Object[] { new Integer(id) };
final User user = new User();
jdbcTemplate.query(sql, values, new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
}
});
return user;
}
public List findByName(String name) {
String sql = "select * from user where name = ?";
Object[] values = new Object[] { name };
//final List users = new ArrayList();
return (List) jdbcTemplate.query(sql, values, new ResultSetExtractor() {
public Object extractData(ResultSet rs) throws SQLException,
DataAccessException {
List users = new ArrayList();
while (rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setPassword(rs.getString("password"));
users.add(user);
}
return users;
}
});
//return users;
}
}
3 总结
3.1 粗浅的比较
在数据展现层方面,asp.net实现了代码和HTML标签元素的彻底分离(比如filename.aspx, filename.aspx.cs),通过回发(postback)对鼠标、键盘等事件进行处理。配套VS2005的可视化编辑功能,代码编写的工作量较小。而这方面J2EE平台上略嫌不足,Struts的配置以及jsp页面上的标签代码编写稍显繁琐(不知JSF对展现层的代码简化程度如何?)。
在业务逻辑方面,asp.net隔离为BLL层,编写业务逻辑控制的相关代码。在J2EE平台上,产生了各种业务逻辑层的开发框架,比如Spring的容器,管理各种业务逻辑对象的生命周期,使得程序员可以更加专注于业务逻辑,同时增加了代码注入和对象组装和灵活配置的能力(AOP,代码反转注入等)
在数据访问层,asp.net采用ADO.net的方式,对SQLServer支持很好,通过System.data.OracleClient亦对Oracle进行了支持。J2EE可以采用jdbc或各种jdbc的封装框架(SpringJdbc, Hibernate/iBatis等),可选择的范围很广,故可根据项目需要进行搭配。
两者之间的差别,很大程度上是由于一个是商业软件,一个是开源社区推动型的两大阵营的差异造成的。从asp.net的三层结构开发的设计思想来看,应该是吸取并借鉴了很多开源框架的优秀设计思想,但总体来说,开源社区更具有活力。
3.2 其它需考虑的问题
关于事务的处理:即将事务控制放在数据访问层还是业务逻辑层?取决于业务的复杂程度,若分布式跨越多个数据库,则在J2EE平台上用JTA,因为JDBC的事务控制局限于当前连接,而一个连接只属于一个数据库。
层之间的接口以及数据传输:ORM映射后,对象和关系(数据库表)建立起了对应关系,j2ee平台用值对象(VO, PO, javabean)来实现数据封装和层之间的传递,asp.net上通常用DataSet,当然也可以用值对象来传输。
如何基于项目需求来选择合适的开发框架:项目的规模,需求特征(如增删改操作和查询操作分别所占的比例),是否数据密集型(使用普通SQL语句或调用存储过程的决定),框架的开发成本和人力成本等各种因素的考虑。
相关文章推荐
- 一个简单的三层结构ASP.NET代码
- asp.net三层结构例子
- ASP.NET中的三层结构
- Asp.net"三层结构"原理与用意学习入门教程(一)
- 上传Excel数据到数据库中(Asp.net自动生成三层代码 第六集 )
- ASP.NET的三层结构
- ASP.NET三层结构演化构建之一——混沌
- ASP.net:三层Web体系结构里的两种数据绑定模式
- C#分析数据库结构,使用XSL模板自动生成代码 - 清清月儿 .NET万花筒 Asp.net技术 Asp.net教程 Asp.net源码 Asp.net基础 Asp.net控件 Asp.net入门 - CSDNBlog
- ASP.NET的三层结构指什么
- 理解ASP.NET中的三层结构
- ASP.NET中的三层结构解读
- ASP.NET的三层结构指什么?
- ASP.NET的三层结构开发模式
- ASP.NET 三层结构
- 用ASP.NET开发三层结构应用程序[转]
- Asp.net三层结构中的变量引用与传递
- 用ASP.NET开发三层结构应用程序-例
- Asp.net三层结构入门示例源码>>SQLserver/SQLHelper.cs
- asp.net 自定义翻页,无需外部dll控件(Asp.net自动生成三层代码 第五集 )