java 使用JDBC构建简单的数据访问层实例详解
本教程的目的是使用Java编写的分离的层去访问数据库中的表,这一层通常称为数据访问层(DAL)
使用DAL的最大好处是通过直接使用一些类似insert()和find()的方法简化了数据库的访问操作,而不是总是先做链接,再执行一些查询。
该层在其内部处理所有与数据库相关的调用和查询。
创建数据库
我们希望为用户创造一个简单的表,我们可以使用这些字段来创建
id int
name varchar(200)
password varchar(200)
age int
数据传输对象
这一层应该包含一个简单的类叫做数据传输对象(DTO)。这个类仅仅是一个与数据库中的表相对应的简单映射,表中的每一列对应类的一个成员变量。
我们的目的是使用简单的Java对象,而不是处理SQL语句和其他与数据库相关的命令来进行数据库的增删改查。
我们想要把表映射成java代码,只需要创建包含相同字段的类(bean)即可
为了更好地封装,除了构造函数我们应该声明所有字段变量为私有,创造访问器(getter和setter),其中有一个是默认的构造函数。
publicclassUser{
privateIntegerid;
privateStringname;
privateStringpass;
privateIntegerage;
}
为了正确地映射字段,我们应该考虑数据库中的NULL值。对于Java的原始的默认值,例如int类型,其默认值是0,所以我们应该提供可容纳空值的新的数据类型。我们可以通过使用特殊的类型——封装类,如Integer来代替INT。
最后我们的类应该像这样:
publicclassUser{
privateIntegerid;
privateStringname;
privateStringpass;
privateIntegerage;
publicUser(){
}
publicUser(Stringname,Stringpass,Integerage){
this.name=name;
this.pass=pass;
this.age=age;
}
publicUser(Integerid,Stringname,Stringpass,Integerage){
this.id=id;
this.name=name;
this.pass=pass;
this.age=age;
}
publicIntegergetAge(){
returnage;
}
publicvoidsetAge(Integerage){
this.age=age;
}
publicIntegergetId(){
returnid;
}
publicvoidsetId(Integerid){
this.id=id;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicStringgetPass(){
returnpass;
}
publicvoidsetPass(Stringpass){
this.pass=pass;
}
}
一个好的做法是,提供默认的空构造函数,一个完整的构造函数和一个没有id参数的完整构造函数。
连接数据库
我们可以使用一个中间类来方便连接到数据库,在这个类中,我们将提供数据库的连接参数如数据库JDBC,URL,用户名和密码,并将这些变量定义成final的(从properties或者xml配置文件中获取这些数据将会更好)
提供一个方法返回一个Connection对象或者当连接失败时返回一个null又或者抛出一个运行时异常。
publicstaticfinalStringURL="jdbc:mysql://localhost:3306/testdb";
publicstaticfinalStringUSER="testuser";
publicstaticfinalStringPASS="testpass";
/**
*获取connection对象
*@returnConnection对象
*/
publicstaticConnectiongetConnection(){
try{
DriverManager.registerDriver(newDriver());
returnDriverManager.getConnection(URL,USER,PASS);
}catch(SQLExceptionex){
thrownewRuntimeException("Errorconnectingtothedatabase",ex);
}
}
我们也可以在类中包含一个主方法来测试连接。完整的类像这样:
importcom.mysql.jdbc.Driver;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.SQLException;
/**
*ConnecttoDatabase
*@authorhany.said
*/
publicclassConnectionFactory{
publicstaticfinalStringURL="jdbc:mysql://localhost:3306/testdb";
publicstaticfinalStringUSER="testuser";
publicstaticfinalStringPASS="testpass";
/**
*Getaconnectiontodatabase
*@returnConnectionobject
*/
publicstaticConnectiongetConnection()
{
try{
DriverManager.registerDriver(newDriver());
returnDriverManager.getConnection(URL,USER,PASS);
}catch(SQLExceptionex){
thrownewRuntimeException("Errorconnectingtothedatabase",ex);
}
}
/**
*TestConnection
*/
publicstaticvoidmain(String[]args){
Connectionconnection=connectionFactory.getConnection();
}
}
数据访问对象
DAO层可以做CRUD操作。它可以对我们的表进行增删改查。
我们的DAO层接口应该像这样:
publicinterfaceUserDao{
UsergetUser();
Set<User>getAllUsers();
UsergetUserByUserNameAndPassword();
booleaninsertUser();
booleanupdateUser();
booleandeleteUser();
}
查找用户
用户可以通过像ID,姓名或邮箱等任何唯一字段来查询。在这个例子中,我们使用ID来查找用户。第一步是通过连接器类来创建一个connection,然后执行SELECT语句以获得其ID为7的用户,我们可以使用这条语句查询用户:
SELECT*FROMuserWHEREid=7
就在这里,我们做了一个动态的语句来从参数中获取ID。
通过执行这个查询,得到一个结果集,其中保存有用户或null。我们可以通过Resultset的next()方法来检测是否有值。如果返回true,我们将继续利用datagetters从ResultSet中获取用户数据。当我们将所有的数据封装到user中后,我们返回它。如果不存在此ID的用户或其他任何异常发生(如无效的SQL语句)这个方法会返回null。
publicUsergetUser(intid){
Connectionconnection=connectionFactory.getConnection();
try{
Statementstmt=connection.createStatement();
ResultSetrs=stmt.executeQuery("SELECT*FROMuserWHEREid="+id);
if(rs.next())
{
Useruser=newUser();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setPass(rs.getString("pass"));
user.setAge(rs.getInt("age"));
returnuser;
}
}catch(SQLExceptionex){
ex.printStackTrace();
}
returnnull;
}
使用单独的方法来从结果集中提取数据将会更方便,因为在很多方法中我们将会调用它。
这个新方法将抛出SQLException并且为了限制只能在类内部使用,其应该是私有的:
privateUserextractUserFromResultSet(ResultSetrs)throwsSQLException{
Useruser=newUser();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setPass(rs.getString("pass"));
user.setAge(rs.getInt("age"));
returnuser;
}
我们上面的方法应该修改成新的方法:
publicUsergetUser(intid){
Connectionconnection=connectionFactory.getConnection();
try{
Statementstmt=connection.createStatement();
ResultSetrs=stmt.executeQuery("SELECT*FROMuserWHEREid="+id);
if(rs.next())
{
returnextractUserFromResultSet(rs);
}
}catch(SQLExceptionex){
ex.printStackTrace();
}
returnnull;
}
登陆方法
登陆操作类似。我们希望提供用户和密码替代ID,这将不会影响参数列表和查询语句。如果用户名和密码是正确的,这个方法会返回一个有效的用户,否则为null。因为有很多的参数,使用PreparedStatement将更有用。
publicUsergetUserByUserNameAndPassword(Stringuser,Stringpass){
Connectorconnector=newConnector();
Connectionconnection=connector.getConnection();
try{
PreparedStatementps=connection.prepareStatement("SELECT*FROMuserWHEREuser=?ANDpass=?");
ps.setString(1,user);
ps.setString(2,pass);
ResultSetrs=ps.executeQuery();
if(rs.next())
{
returnextractUserFromResultSet(rs);
}
}catch(SQLExceptionex){
ex.printStackTrace();
}
returnnull;
}
查询所有用户的方法
这个方法将会返回所有的用户,所以我们应该将它们存在一个类似数组的容器中返回来。但是,因为我们不知道有多少条记录。使用例如Set或者List的集合将会更好:
publicSetgetAllUsers(){
Connectorconnector=newConnector();
Connectionconnection=connector.getConnection();
try{
Statementstmt=connection.createStatement();
ResultSetrs=stmt.executeQuery("SELECT*FROMuser");
Setusers=newHashSet();
while(rs.next())
{
Useruser=extractUserFromResultSet(rs);
users.add(user);
}
returnusers;
}catch(SQLExceptionex){
ex.printStackTrace();
}
returnnull;
}
插入方法
Insert方法将采取用户作为参数,并使用PreparedStatement对象来执行SQLupdate语句。executeUpdate方法返回受影响的行数。如果我们添加单行,意味着该方法应该返回1,如果是这样,我们返回true,否则,我们返回false
publicbooleaninsertUser(Useruser){
Connectorconnector=newConnector();
Connectionconnection=connector.getConnection();
try{
PreparedStatementps=connection.prepareStatement("INSERTINTOuserVALUES(NULL,?,?,?)");
ps.setString(1,user.getName());
ps.setString(2,user.getPass());
ps.setInt(3,user.getAge());
inti=ps.executeUpdate();
if(i==1){
returntrue;
}
}catch(SQLExceptionex){
ex.printStackTrace();
}
returnfalse;
}
更新方法
更新方法和插入方法类似。唯一变化的是SQL语句
publicbooleanupdateUser(Useruser){
Connectorconnector=newConnector();
Connectionconnection=connector.getConnection();
try{
PreparedStatementps=connection.prepareStatement("UPDATEuserSETname=?,pass=?,age=?WHEREid=?");
ps.setString(1,user.getName());
ps.setString(2,user.getPass());
ps.setInt(3,user.getAge());
ps.setInt(4,user.getId());
inti=ps.executeUpdate();
if(i==1){
returntrue;
}
}catch(SQLExceptionex){
ex.printStackTrace();
}
returnfalse;
}
删除方法
删除的方法是使用一个简单的查询像
DELETEFROMuserWHEREID=7
带上id参数发送该查询将删除此记录。如果成功删除将返回1
publicbooleandeleteUser(intid){
Connectorconnector=newConnector();
Connectionconnection=connector.getConnection();
try{
Statementstmt=connection.createStatement();
inti=stmt.executeUpdate("DELETEFROMuserWHEREid="+id);
if(i==1){
returntrue;
}
}catch(SQLExceptionex){
ex.printStackTrace();
}
returnfalse;
}
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!