用DAO模式操作数据库(未运行)
作者:admin 日期:2007-08-12
DAO(Data Access Object,数据访问对象),是Java编程中的一种经典模式,正被广泛应用,也是J2EE架构中持久层框架的基础知识,基于分层次式的软件架构来实现对数据库的访问操作。
DAO模式的主要思想就是从抽象数据源获取与操纵数据的方法。抽象数据的含义就是编写应用程序的程序员不必关心数据库的物理位置,是何种数据库,只须使用封装数据库中表示记录的数据对象即可。
图中BusinessObject业务对象,是使用DAO模式的客户端;DataTransferObject数据传输对象,在应用程序不同层次之间传输对象,在一个分布式应用程序中,通常可以提高整体的性能;DataAccessObject数据输入/输出对象封装了对数据源的一些基本的操作;DataSource指的是数据源。也可以从图中看出,DAO模式分离了业务逻辑和数据逻辑,使得编写的软件具有良好的层次式体系结构。
DAO模式中对于数据库的访问,可以使用任意的Java数据访问方式,如JDBC API、EJB, JDO/Hibernate以及任何其他的ORM(对象关系映射工具)。
【实例66】 用DAO模式操作数据库
下面是一个相对复杂的应用实例,一方面理解DAO模式操作数据库的分层式软件开发思想,另一方面结合第7章中用.properties作数据库连接配置文件的方法,并用JavaBean来实现对配置文件中属性值的读取。
本例不再使用ROOT(Tomcat默认的Web应用),而使用一个新的Web应用——dao。建立一个应用最简单的方法就是在Tomcat 5.5的安装目录下的webapps子文件夹中创建一个文件夹,命名为“dao”,文件夹结构如图8-12所示。
从上图可以看出,类的组织层次上共有3个包,DAO.connDB包中存放与数据库连接相关的类;DAO.table包中存放封装表的类;DAO.tableOP包中存放对表操作的类;数据库连接的配置文件dbconn.properties位于classes目录中。类之间的调用关系如下:
所有代码如下:
dbconn.properties文件存放连接数据库的配置参数,内容如下:
dbconn.properties
#SQL Server
driverName=com.microsoft.jdbc.sqlserver.SQLServerDriver connString=jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=testDatabase
userName=sa
password=6599996
DAO.connDB.readPropertie类用来读取.properties文件中的配置,其源代码如下:
readProperties.java
package DAO.connDB;
import java.io.InputStream;
import java.util.Properties;
//读.properties文件属性类
public class readProperties {
String propertyFileName=null;//.properties文件名称
public String getPropertyFileName() {
return propertyFileName;
}
public void setPropertyFileName(String propertyFileName) {
this.propertyFileName = propertyFileName;
}
public String getPropertyFromFile(String refName)
{//从.properties文件中得到refName属性的值
if(this.getPropertyFileName()==null) return null;
else{
try{
InputStream fin = getClass().getResourceAsStream(this. get Property FileName());
Properties props = new Properties();
props.load(fin);
return (String)props.getProperty(refName);
}catch(Exception e){
return null;
}
}
}
}
DAO.connDB.conndb封装了对数据库的连接,通过DAO.connDB.readProperties类读取连接参数,其源代码如下:
conndb.java
package DAO.connDB;
import java.sql.Connection;
import java.sql.DriverManager;
//生成数据库连接对象类
public class connDB {
String driverName=null;//数据库驱动名
String connString=null;//连接字符串
String userName=null;//用户名
String password=null;//密码
public connDB() {//在构造函数中初始化数据库连接参数
readProperties readDBProperties=new readProperties();
readDBProperties.setPropertyFileName("/dbconn.properties");
driverName=readDBProperties.getPropertyFromFile("driverName");
connString=readDBProperties.getPropertyFromFile("connString");
userName=readDBProperties.getPropertyFromFile("userName");
password=readDBProperties.getPropertyFromFile("password");
}
public Connection getDBConn()
{//得到数据库连接对象
if(driverName==null||connString==null||userName==null) return null;
else{
try{
Connection connDBObject=null;
Class.forName(driverName);
return DriverManager.getConnection(connString, userName, password);
}catch(Exception e){
return null;
}
}
}
public String getConnString() {
return connString;
}
public String getDriverName() {
return driverName;
}
public String getPassword() {
return password;
}
public String getUserName() {
return userName;
}
}
DAO.table.userRecord类封装了数据库中的userTable表记录,源代码如下:
UserRecord.java
package DAO.table;
import java.sql.Date;
//封闭数据库userTable表记录的类
public class userRecord {
long userId;//用户ID
String userName;//用户名
String userPassword;//用户密码
String userTrueName;//用户真实姓名
int userAge;//用户年龄
String userSex;//用户性别
String userAddress;//用户地址
String userTelephone;//用户电话号码
Date addTime; //增加用户的时间
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public String getUserTelephone() {
return userTelephone;
}
public void setUserTelephone(String userTelephone) {
this.userTelephone = userTelephone;
}
public String getUserTrueName() {
return userTrueName;
}
public void setUserTrueName(String userTrueName) {
this.userTrueName = userTrueName;
}
public Date getAddTime() {
return addTime;
}
public void setAddTime(Date addTime) {
this.addTime = addTime;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
public int getUserAge() {
return userAge;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
}
从上面的代码可以看出,针对数据库中的userTable表的字段都一个userRecord类的属性相对应,并有getXxxx()和setXxxx()方法,如果使用了Eclipse或JBuilder这样的可视化开发环境,书写了类的属性后,相应的 getXxxx()和setXxxx()方法都可以用功能菜单快速自动生成。
DAO.tableOP.uerDAO类中编写对userTable表的操作,为简便起见,这里只编写了根据用户名查找用户的方法,实际应用中可以根据需要增加方法。其源代码如下:
UserDAO.java
package DAO.tableOP;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Hashtable;
import DAO.table.userRecord;
import DAO.connDB.connDB;
//userTable表DAO操作类
public class userDAO {
Connection conn=null;
public userDAO() {//在构造函数中初始化数据库连接
conn=(new connDB()).getDBConn();
}
public Hashtable getUsersByUserName(String userName)
{//根据用户名查找用户,支持模糊查询,输入参数为JSP页面输入的查询姓名,
//返回用户记录对象集的Hashtable(哈希表)
Hashtable usersHashTable=new Hashtable();
String sqlString=null;
//构造SQL语句
if(userName==null||userName.length()==0)
sqlString="select * from userTable";
else
sqlString="select * from userTable where user_true_name like '%"+userName+"%'";
if(conn!=null){
Statement SQLQueryObject=null;
ResultSet RecordSet=null;
try{
//查询出数据
SQLQueryObject=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
RecordSet=SQLQueryObject.executeQuery(sqlString);
//循环地把数据放入Hashtable
int i=0;
userRecord user=new userRecord();
while(RecordSet.next()){
user.setUserId(RecordSet.getLong("user_id"));
user.setUserName(RecordSet.getString("user_name")); user.setUserPassword(RecordSet.getString("user_password"));
user.setUserSex(RecordSet.getString("user_sex"));
user.setUserTelephone(RecordSet.getString("user_telephone"));
user.setUserTrueName(RecordSet.getString("user_true_name"));
user.setUserAge(RecordSet.getInt("user_age"));
user.setUserAddress(RecordSet.getString("user_address"));
user.setAddTime(RecordSet.getDate("add_time"));
usersHashTable.put("user"+i,user);
i++;
user=new userRecord();
}
}catch(Exception e){
e.printStackTrace();
}
}
return usersHashTable;
}
}
在该程序中,把查询出的用户信息放入userRecord类的对象user中,然后再放入hashTable。在user对象中需要用new关键字再新生成一个,这是因为hashTable在内存中作了映射,如果不新生成一个user对象,在while循环中,设置user属性等于是更改了原user对象的属性,放入hashTable中的对象仍然指向此对象,会使得hashTable中的对象内容相同,因此每在hashTable中放入一个user对象后,需要用user=new userRecord()语句来新生成一个user对象。
应用层通过调用userDAO类完成所需的操作。这里的应用层是一个JSP页面,其源代码如下:
userDAOExample.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ pageimport="java.sql.*,DAO.tableOP.*,DAO.table.*,java.util.Hashtable" %>
<%!
public String codeToString(String str)
{//处理中文字符串的函数
String s=str;
try{
byte tempB[]=s.getBytes("ISO-8859-1");
s=new String(tempB);
return s;
}catch(Exception e)
{return s;
}
}
%>
<%//根据条件查询出数据,放入Hashtable对象中
String username= codeToString(request.getParameter("username"));
userDAO userDAOObject=new userDAO();
Hashtable users=userDAOObject.getUsersByUserName(username);
%>
<HTML>
<BODY>
<Table Border>
<form action=userDAOExample.jsp method=post>
<TR>
<td>查询姓名</td>
<td colspan=7><input type=text name=username><input type=submit value=提交></td>
</tr>
</form>
<TR>
<td colspan=8 align=center>用户数据(共<%%>条记录)</td>
</tr>
<TR>
<Td width=100 >用户ID号</td>
<Td width=50 >用户名</td>
<Td width=100>用户真实姓名</td>
<Td width=50>年龄</td>
<Td width=50>性别</td>
<Td width=100>联系地址</td>
<Td width=100>联系电话</td>
<Td width=100>添加时间</td>
</TR>
<%//输出查询出的数据
if(users!=null)
{
for(int i=0;i<users.size();i++)
{
%>
<TR>
<TD><%=((userRecord)users.get("user"+i)).getUserId()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getUserName()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getUserTrueName()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getUserAge()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getUserSex()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getUserAddress()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getUserTelephone()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getAddTime()%></TD>
</TR>
<%
}
}
%>
</Table>
</BODY>
</HTML>
从上述代码中可以发现,在JSP页同中的Java代码已经很少,只是接收提交要查找的用户名后,用userDAO类的方法来得到查询结果hashTable,再用for循环来输出此hashTable中的内容。该程序的运行结果(第一次打开页面查询出所有的用户的用户信息)如图8-14所示:
点击下载此文件
DAO模式的主要思想就是从抽象数据源获取与操纵数据的方法。抽象数据的含义就是编写应用程序的程序员不必关心数据库的物理位置,是何种数据库,只须使用封装数据库中表示记录的数据对象即可。
图中BusinessObject业务对象,是使用DAO模式的客户端;DataTransferObject数据传输对象,在应用程序不同层次之间传输对象,在一个分布式应用程序中,通常可以提高整体的性能;DataAccessObject数据输入/输出对象封装了对数据源的一些基本的操作;DataSource指的是数据源。也可以从图中看出,DAO模式分离了业务逻辑和数据逻辑,使得编写的软件具有良好的层次式体系结构。
DAO模式中对于数据库的访问,可以使用任意的Java数据访问方式,如JDBC API、EJB, JDO/Hibernate以及任何其他的ORM(对象关系映射工具)。
【实例66】 用DAO模式操作数据库
下面是一个相对复杂的应用实例,一方面理解DAO模式操作数据库的分层式软件开发思想,另一方面结合第7章中用.properties作数据库连接配置文件的方法,并用JavaBean来实现对配置文件中属性值的读取。
本例不再使用ROOT(Tomcat默认的Web应用),而使用一个新的Web应用——dao。建立一个应用最简单的方法就是在Tomcat 5.5的安装目录下的webapps子文件夹中创建一个文件夹,命名为“dao”,文件夹结构如图8-12所示。
从上图可以看出,类的组织层次上共有3个包,DAO.connDB包中存放与数据库连接相关的类;DAO.table包中存放封装表的类;DAO.tableOP包中存放对表操作的类;数据库连接的配置文件dbconn.properties位于classes目录中。类之间的调用关系如下:
所有代码如下:
dbconn.properties文件存放连接数据库的配置参数,内容如下:
dbconn.properties
#SQL Server
driverName=com.microsoft.jdbc.sqlserver.SQLServerDriver connString=jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=testDatabase
userName=sa
password=6599996
DAO.connDB.readPropertie类用来读取.properties文件中的配置,其源代码如下:
readProperties.java
package DAO.connDB;
import java.io.InputStream;
import java.util.Properties;
//读.properties文件属性类
public class readProperties {
String propertyFileName=null;//.properties文件名称
public String getPropertyFileName() {
return propertyFileName;
}
public void setPropertyFileName(String propertyFileName) {
this.propertyFileName = propertyFileName;
}
public String getPropertyFromFile(String refName)
{//从.properties文件中得到refName属性的值
if(this.getPropertyFileName()==null) return null;
else{
try{
InputStream fin = getClass().getResourceAsStream(this. get Property FileName());
Properties props = new Properties();
props.load(fin);
return (String)props.getProperty(refName);
}catch(Exception e){
return null;
}
}
}
}
DAO.connDB.conndb封装了对数据库的连接,通过DAO.connDB.readProperties类读取连接参数,其源代码如下:
conndb.java
package DAO.connDB;
import java.sql.Connection;
import java.sql.DriverManager;
//生成数据库连接对象类
public class connDB {
String driverName=null;//数据库驱动名
String connString=null;//连接字符串
String userName=null;//用户名
String password=null;//密码
public connDB() {//在构造函数中初始化数据库连接参数
readProperties readDBProperties=new readProperties();
readDBProperties.setPropertyFileName("/dbconn.properties");
driverName=readDBProperties.getPropertyFromFile("driverName");
connString=readDBProperties.getPropertyFromFile("connString");
userName=readDBProperties.getPropertyFromFile("userName");
password=readDBProperties.getPropertyFromFile("password");
}
public Connection getDBConn()
{//得到数据库连接对象
if(driverName==null||connString==null||userName==null) return null;
else{
try{
Connection connDBObject=null;
Class.forName(driverName);
return DriverManager.getConnection(connString, userName, password);
}catch(Exception e){
return null;
}
}
}
public String getConnString() {
return connString;
}
public String getDriverName() {
return driverName;
}
public String getPassword() {
return password;
}
public String getUserName() {
return userName;
}
}
DAO.table.userRecord类封装了数据库中的userTable表记录,源代码如下:
UserRecord.java
package DAO.table;
import java.sql.Date;
//封闭数据库userTable表记录的类
public class userRecord {
long userId;//用户ID
String userName;//用户名
String userPassword;//用户密码
String userTrueName;//用户真实姓名
int userAge;//用户年龄
String userSex;//用户性别
String userAddress;//用户地址
String userTelephone;//用户电话号码
Date addTime; //增加用户的时间
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public String getUserTelephone() {
return userTelephone;
}
public void setUserTelephone(String userTelephone) {
this.userTelephone = userTelephone;
}
public String getUserTrueName() {
return userTrueName;
}
public void setUserTrueName(String userTrueName) {
this.userTrueName = userTrueName;
}
public Date getAddTime() {
return addTime;
}
public void setAddTime(Date addTime) {
this.addTime = addTime;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
public int getUserAge() {
return userAge;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
}
从上面的代码可以看出,针对数据库中的userTable表的字段都一个userRecord类的属性相对应,并有getXxxx()和setXxxx()方法,如果使用了Eclipse或JBuilder这样的可视化开发环境,书写了类的属性后,相应的 getXxxx()和setXxxx()方法都可以用功能菜单快速自动生成。
DAO.tableOP.uerDAO类中编写对userTable表的操作,为简便起见,这里只编写了根据用户名查找用户的方法,实际应用中可以根据需要增加方法。其源代码如下:
UserDAO.java
package DAO.tableOP;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Hashtable;
import DAO.table.userRecord;
import DAO.connDB.connDB;
//userTable表DAO操作类
public class userDAO {
Connection conn=null;
public userDAO() {//在构造函数中初始化数据库连接
conn=(new connDB()).getDBConn();
}
public Hashtable getUsersByUserName(String userName)
{//根据用户名查找用户,支持模糊查询,输入参数为JSP页面输入的查询姓名,
//返回用户记录对象集的Hashtable(哈希表)
Hashtable usersHashTable=new Hashtable();
String sqlString=null;
//构造SQL语句
if(userName==null||userName.length()==0)
sqlString="select * from userTable";
else
sqlString="select * from userTable where user_true_name like '%"+userName+"%'";
if(conn!=null){
Statement SQLQueryObject=null;
ResultSet RecordSet=null;
try{
//查询出数据
SQLQueryObject=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
RecordSet=SQLQueryObject.executeQuery(sqlString);
//循环地把数据放入Hashtable
int i=0;
userRecord user=new userRecord();
while(RecordSet.next()){
user.setUserId(RecordSet.getLong("user_id"));
user.setUserName(RecordSet.getString("user_name")); user.setUserPassword(RecordSet.getString("user_password"));
user.setUserSex(RecordSet.getString("user_sex"));
user.setUserTelephone(RecordSet.getString("user_telephone"));
user.setUserTrueName(RecordSet.getString("user_true_name"));
user.setUserAge(RecordSet.getInt("user_age"));
user.setUserAddress(RecordSet.getString("user_address"));
user.setAddTime(RecordSet.getDate("add_time"));
usersHashTable.put("user"+i,user);
i++;
user=new userRecord();
}
}catch(Exception e){
e.printStackTrace();
}
}
return usersHashTable;
}
}
在该程序中,把查询出的用户信息放入userRecord类的对象user中,然后再放入hashTable。在user对象中需要用new关键字再新生成一个,这是因为hashTable在内存中作了映射,如果不新生成一个user对象,在while循环中,设置user属性等于是更改了原user对象的属性,放入hashTable中的对象仍然指向此对象,会使得hashTable中的对象内容相同,因此每在hashTable中放入一个user对象后,需要用user=new userRecord()语句来新生成一个user对象。
应用层通过调用userDAO类完成所需的操作。这里的应用层是一个JSP页面,其源代码如下:
userDAOExample.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<%@ pageimport="java.sql.*,DAO.tableOP.*,DAO.table.*,java.util.Hashtable" %>
<%!
public String codeToString(String str)
{//处理中文字符串的函数
String s=str;
try{
byte tempB[]=s.getBytes("ISO-8859-1");
s=new String(tempB);
return s;
}catch(Exception e)
{return s;
}
}
%>
<%//根据条件查询出数据,放入Hashtable对象中
String username= codeToString(request.getParameter("username"));
userDAO userDAOObject=new userDAO();
Hashtable users=userDAOObject.getUsersByUserName(username);
%>
<HTML>
<BODY>
<Table Border>
<form action=userDAOExample.jsp method=post>
<TR>
<td>查询姓名</td>
<td colspan=7><input type=text name=username><input type=submit value=提交></td>
</tr>
</form>
<TR>
<td colspan=8 align=center>用户数据(共<%%>条记录)</td>
</tr>
<TR>
<Td width=100 >用户ID号</td>
<Td width=50 >用户名</td>
<Td width=100>用户真实姓名</td>
<Td width=50>年龄</td>
<Td width=50>性别</td>
<Td width=100>联系地址</td>
<Td width=100>联系电话</td>
<Td width=100>添加时间</td>
</TR>
<%//输出查询出的数据
if(users!=null)
{
for(int i=0;i<users.size();i++)
{
%>
<TR>
<TD><%=((userRecord)users.get("user"+i)).getUserId()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getUserName()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getUserTrueName()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getUserAge()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getUserSex()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getUserAddress()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getUserTelephone()%></TD>
<TD><%=((userRecord)users.get("user"+i)).getAddTime()%></TD>
</TR>
<%
}
}
%>
</Table>
</BODY>
</HTML>
从上述代码中可以发现,在JSP页同中的Java代码已经很少,只是接收提交要查找的用户名后,用userDAO类的方法来得到查询结果hashTable,再用for循环来输出此hashTable中的内容。该程序的运行结果(第一次打开页面查询出所有的用户的用户信息)如图8-14所示:
点击下载此文件
评论: 0 | 引用: 0 | 查看次数: 3044
发表评论
你没有权限发表留言!