用Java实现数据库应用系统
副标题#e#
我们在做信息系统的时候,都要会见数据库,我最近接办一个项目,项目组抉择利用Java编写,我认真数据层的设计和编码,为了提高代码的重用性和提高项目标开拓效率。我们开拓了一个通用的数据库毗连和完成根基操纵的类库,小我私家认为这个类在做MIS系统时照旧有必然的代价,所以总结出来,先容给各人。
毗连工场,实现了DataSource接口
package skydev.modules.data;
import java.sql.*;
import javax.sql.DataSource;
import java.io.PrintWriter;
public class ConnectionFactory implements DataSource {
private String userName;
private String password;
private String driverName;
private String url;
private java.sql.Connection connection;
/**
* 按照配置的毗连参数建设一个新的毗连实例
* @return
*/
private Connection getNewConnection() {
try {
this.connection.close(); //试图封锁毗连
}
finally {
this.connection = null; //释放毗连
try {
Class.forName(this.driverName); //加载驱动措施
//DriverManager.registerDriver(driver);
try {
this.connection = DriverManager.getConnection(this.url, this.userName,
this.password);
}
catch (SQLException e) {
throw e;
}
}
finally {
return this.connection; //返回新成立的毗连
}
}
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDriverName() {
return driverName;
}
public void setDriverName(String driverName) {
this.driverName = driverName;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public java.sql.Connection getConnection() {
if (connection != null) {
try {
if (connection.isClosed()) {
connection = null;
getNewConnection();
}
}
catch (SQLException ex) {
}
}
if (connection == null) { //没有配置毗连则建设一个毗连
getNewConnection();
}
return connection;
}
public Connection getConnection(String userName, String password) throws
SQLException {
this.setUserName(userName);
this.setPassword(password);
return getConnection();
}
public PrintWriter getLogWriter() {
return null;
}
public void setLogWriter(PrintWriter printWriter) {
}
public void setLoginTimeout(int int0) {
}
public int getLoginTimeout() {
return 0;
}
}
#p#副标题#e#
实现毗连SQLServer的毗连工场,这里因为我们的项目利用SQLServer2000所以只实现了SqlServerConnectionFactory。
package skydev.modules.data;
public final class SqlServerConnectionFactory extends ConnectionFactory {
private final String dbDriver ="com.microsoft.jdbc.sqlserver.SQLServerDriver";
private String host;//主机
private int port;//端口
private String databaseName;//Sql数据库名称
public SqlServerConnectionFactory() {
super.setDriverName(dbDriver);
}
/**
*
* @param host 数据库地址的主机名:如"localhost"
* @param port SQL处事器运行的端标语,假如利用缺省值 1433,传入一个负数即可
* @param databaseName 数据库名称
* @param userName 用户名
* @param password 口令
*/
public SqlServerConnectionFactory(String host,
int port,
String databaseName,
String userName,
String password) {
this.setHost(host);
this.setPort(port);
this.setDatabaseName(databaseName);
this.setUserName(userName);
this.setPassword(password);
init();
}
private void init() {
super.setDriverName(dbDriver);
super.setUrl("jdbc:microsoft:sqlserver://" + host.trim() + ":" +
new Integer(port).toString() + ";DatabaseName=" +
databaseName.trim());
//super.setUrl("jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=demo");
}
public void setHost(String host) {
//处理惩罚主机名称
if ( (host == null) || (host.equals("")) || (host.equals(".")) ||
(host.equals("local"))) {
host = "localhost";
}
int index = host.indexOf("//", 0);
if (index == 0) {
host = host.substring(2); //去掉前面的"//"
}
index = host.indexOf("//", 0);
if (index >= 0) {
try {
throw new Exception("SQL Server主机名参数错误!");
}
catch (Exception ex) {
}
}
this.host = host;
}
public void setPort(int port) {
/**
* 缺省端口1433
*/
if (port < 0) {
port = 1433;
}
this.port = port;
}
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
}
利用"sun.jdbc.odbc.JdbcOdbcDriver"毗连数据库的毗连工场
package skydev.modules.data;
public class JdbcOdbcConnectionFactory extends ConnectionFactory {
private final static String driveName = "sun.jdbc.odbc.JdbcOdbcDriver";
private String odbcName;
public JdbcOdbcConnectionFactory() {
super.setDriverName(driveName);
}
/**
*利用指定的Odbc数据源毗连数据库处事器
* @param odbcName
*/
public JdbcOdbcConnectionFactory(String odbcName) {
super.setDriverName(driveName);
setOdbcName(odbcName);
}
public void setOdbcName(String odbcName) {
this.odbcName = odbcName;
this.setUrl("jdbc:odbc:" + odbcName);
}
}
数据根基操纵类,利用毗连工场毗连数据库。
#p#分页标题#e#
package skydev.modules.data;
import java.sql.*;
import java.sql.PreparedStatement;
import javax.sql.DataSource;
public abstract class DatabaseObject {
protected Connection connection = null;
protected ResultSet resultSet = null;
protected ResultSetMetaData resultSetMetaData = null;
private ConnectionFactory connectionFactory = null;
private java.sql.Statement statement=null;
private javax.sql.DataSource dataSource;//=new Statement();
public DatabaseObject(){
dataSource=null;
connection=null;
}
public DatabaseObject(ConnectionFactory connectionFactory) {
this.setConnectionFactory(connectionFactory);
this.dataSource=connectionFactory;//ConnectionFactory实现了DataSource接口
}
/**
* 执行查询
* @param sql 要执行的Sql语句
* @return 返回查询的功效集 ,查询失败返回null
*/
public ResultSet getResultSet(String sql) {
try {
this.resultSet = statement.executeQuery(sql); //保存内部指针
}
catch (SQLException e) {
e.printStackTrace();
this.resultSet = null;
}
finally {
return this.resultSet;
}
}
/**
* 获取外部指定ResltSet的ResultSetMetaData数据
* @param resultSet 要获取的ResultSet
* @return 失败返回null
*/
public ResultSetMetaData getResultSetMetaData(ResultSet resultSet) {
ResultSetMetaData resultSetMetaData = null;
try {
resultSetMetaData = resultSet.getMetaData();
}
catch (SQLException e) {
e.printStackTrace();
resultSetMetaData = null;
}
finally {
return resultSetMetaData;
}
}
/**
* 获取最近一次配置可能返回的ResultSet的ResultMetaData数据,
* 例如说挪用了:getResultSet(sql)要领,然后挪用getResultSetMetaData要领
* 可以得到相应的ResultSetMetaData数据。
* @return
*/
public ResultSetMetaData getResultSetMetaData() {
return this.getResultSetMetaData(this.resultSet);
}
/**
* 执行存储进程
* @param spName 存储进程名称
* @return
*/
public ResultSet Execute(String spName) {
//对此数据库执行一个 SQL 查询
ResultSet resultSet = null;
try {
// PreparedStatement stmt = (PreparedStatement) connection.createStatement();
resultSet = statement.executeQuery(spName);
}
catch (Exception e) {
System.out.println("execute error" + e.getMessage());
}
return resultSet;
}
/**
* 配置数据库毗连工场,对此类的所有操纵之前,必需挪用该要领,
* 配置数据库毗连工场。
* @param connectionFactory 数据库毗连工场ConnectionFactory 类工具以及
* 派生类工具。
*/
public void setConnectionFactory(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
connection = connectionFactory.getConnection();
try {
statement = connection.createStatement();
}
catch (SQLException ex) {
System.err.println(ex);
}
}
public Connection getConnection() {
return connection;
}
public java.sql.Statement getStatement() {
return statement;
}
public javax.sql.DataSource getDataSource() {
return dataSource;
}
}
详细项目标数据库会见基类
#p#分页标题#e#
package skydev.modules.data;
public class DbObject extends DatabaseObject {
// private final static String driveName = "sun.jdbc.obdc.JdbcOdbcDriver";
public DbObject() {
super(new SqlServerConnectionFactory("localhost", 1433, "TheSchool", "sa",""));
}
public DbObject(ConnectionFactory connectionFactory) {
super(connectionFactory);
}
}
在项目中的数据库层中的数据库会见类都从DatabaseObject类派生,这样只需要在一个处所配置数据毗连,其他处所都不需要涉及数据库会见的详细毗连代码。
如:User类专门认真Users组的权限节制等,只需要简朴的代码就可以毗连并会见数据库了。这里详细实 现与此文章无关,只举一两个模块做例子。
public class User extends DbObject {
public User() {
//子类也可以包围基类的会见方法,在单机调式时有用。
// super(new SqlServerConnectionFactory("localhost", 1433, "TheSchool", "sa",""));
super();//挪用基类的数据库会见代码。
}
/*
在做信息系统时为了提高客维护性,我们一般利用存储进程返回和修改数据,在数据库层代码不利用
Select语句直接检索数据,做到数据库层代码的最大的机动性和可维护性。一旦发明需要修改数据库中的
代码,只需要修改村年头进程即可以。
下面先容Java利用SqlServer StoreProcedure的要领。
存储进程的参数利用“?”取代,下面的代码有必然的代表性,存储进程有输入参数,输出参数。
存储进程的根基成果为:检测userID和encPassword是否和数据库存储的一致,返回UserID,假如纷歧
致返回-1。
*/
//测试数据库中存储的已经加密的暗码和用户传入的加密的暗码是否一致。
public boolean testPassword(int userID, byte[] encPassword) {
Connection con = this.getConnection();
CallableStatement cs = null;
try {
cs = con.prepareCall("{?=call sp_Accounts_TestPassword(?,?)}");
cs.setInt(2, userID);
cs.setBytes(3, encPassword);
cs.registerOutParameter(1, Types.INTEGER); //@UserID
cs.execute();
if (cs.getInt(1) == 1) { //暗码及格
return true;
}
else {
return false;
}
}
catch (SQLException ex) {
return false;
}
catch (Exception e) {
return false;
}
}
}
以上只是我在进修和事情中的一点体会,写出来的目标使为了和各人交换,错误之处但愿各人提着名贵的意见,以便把该模块的成果做得更完善一点。