JDBC编程之程序优化
-----------------siwuxie095
首先下载 MySQL 的 JDBC 驱动,下载链接:
https://dev.mysql.com/downloads/connector/j/
mysql-connector-java-5.1.41.zip 解压后一览:
工程名:JDBCTest
包名:com.siwuxie095.util、com.siwuxie095.entity、com.siwuxie095.dao、
com.siwuxie095.dao.impl、com.siwuxie095.test
类名:ConnectionFactory.java、StuIdEntity.java、StuInfo.java、StuPassword.java、
StuInfoDao.java、StuPasswordDao.java、StuInfoDaoImpl.java、
StuPasswordDaoImpl.java、DaoTest.java(主类)
点击选择 src,右键->New->File,创建文件:dbconfig.properties
打开资源管理器,在工程 JDBCTest 文件夹下,创建一个文件夹:lib,
在其中放入:mysql-connector-java-5.1.41-bin.jar
选择 mysql-connector-java-5.1.41-bin.jar,右键->Build Path->Add to Build Path
此时,工程结构目录一览:
ConnectionFactory.java:
package com.siwuxie095.util;
import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties;
//数据库连接工厂类 public class ConnectionFactory { //四个成员变量用于保存从属性文件中读取到的数据库配置信息 private static String driver; private static String dburl; private static String user; private static String password; //定义ConnectionFactory类型的成员变量 private static final ConnectionFactory factory=new ConnectionFactory(); //定义Connection类型的成员变量,用于保存数据库连接 private Connection conn; /** * 用 static 声明一个静态代码块 * 静态代码块用于初始化类,可以为类的属性赋值 * * 当JVM加载类时,会执行其中的静态代码块 * * 因为是在加载类的过程中执行的,所以静态代码块只会执行一次 * * 这里是从属性文件中读取相关的配置信息 */ static{ /** * 创建一个 Properties 对象,Properties 在 java.util 包中, * 继承自 Hashtable 类,可以用来保存属性文件中的键值对, * Properties 的方法专门用于处理属性文件中的键值对 */ Properties prop=new Properties(); try { /** * 获取属性文件中的内容: * 首先获取当前类的类加载器,使用类加载器的getResourceAsStream()方法, * 读取属性文件中内容,并读取到一个输入流中 */ InputStream in=ConnectionFactory.class.getClassLoader() .getResourceAsStream("dbconfig.properties"); //从输入流中读取属性列表,即键值对 prop.load(in); } catch (Exception e) { System.out.println("========配置文件读取错误========"); } //将读取到的值赋值给成员变量 driver=prop.getProperty("driver"); dburl=prop.getProperty("dburl"); user=prop.getProperty("user"); password=prop.getProperty("password"); //属性文件的加载---编写完成 } //定义一个默认构造方法(空的构造方法) //构造方法私有化是单例化一个类的第一步 private ConnectionFactory(){ } //定义getInstance()方法,用来获取一个ConnectionFactory的实例 //单例模式,保证在程序运行期间,只有一个ConnectionFactory实例存在 public static ConnectionFactory getInstance() { return factory; } //创建一个获取数据库连接的方法 makeConnection() public Connection makeConnection() { try { Class.forName(driver); conn=DriverManager.getConnection(dburl,user,password); } catch (Exception e) { e.printStackTrace(); } return conn; } } |
StuIdEntity.java:
package com.siwuxie095.entity;
/** * 定义一个所有实体类(DTO)的父类:StuIdEntity * StuIdEntity 只有一个属性:stuId * * 因为所有的表都会有一个没有业务含义的主键id:stu_id * StuIdEntity 类就是封装了这个非业务的主键信息 * * 同时 StuIdEntity.java 也是抽象类,其子类为: * StuInfo.java 和 StuPassword.java * * StuInfo.java 和 StuPassword.java 也是两个DTO类, * 分别对应之前创建的stu_password表和stu_info表 * * DTO 即 Data Transfer Object,数据传输对象 * * DTO 主要用于远程调用等需要大量传输对象的地方 * * DTO类一般只有成员变量、getter和setter方法、构造函数 * * DTO 不能包含业务逻辑 * */ public abstract class StuIdEntity { protected String stuId;
public String getStuId() { return stuId; }
public void setStuId(String stuId) { this.stuId = stuId; } } |
StuInfo.java:
package com.siwuxie095.entity;
/** * StuInfo 继承自 StuIdEntity * 即它也是一个 DTO 类(实体类) * * @author siwux * */ public class StuInfo extends StuIdEntity { //这些属性和数据库中 stu_info 表中的字段对应 private String stuName; private String stuSex; private String stuAcademic; private String stuMajor;
public String getStuName() { return stuName; }
public void setStuName(String stuName) { this.stuName = stuName; }
public String getStuSex() { return stuSex; }
public void setStuSex(String stuSex) { this.stuSex = stuSex; }
public String getStuAcademic() { return stuAcademic; }
public void setStuAcademic(String stuAcademic) { this.stuAcademic = stuAcademic; }
public String getStuMajor() { return stuMajor; }
public void setStuMajor(String stuMajor) { this.stuMajor = stuMajor; }
//覆盖toString()方法 @Override public String toString() { return "StuInfo [stuName=" + stuName + ", stuSex=" + stuSex + ", stuAcademic=" + stuAcademic + ", stuMajor="+ stuMajor + ", stuId=" + stuId + "]"; }
} |
StuPassword.java:
package com.siwuxie095.entity;
/** * StuPassword 继承自 StuIdEntity * 即它也是一个 DTO 类(实体类) * * @author siwux * */ public class StuPassword extends StuIdEntity {
//stuPwd 和数据库中 stu_password 表中的字段对应 private String stuPwd;
public String getStuPwd() { return stuPwd; }
public void setStuPwd(String stuPwd) { this.stuPwd = stuPwd; }
//覆盖 toString()方法 @Override public String toString() { return "StuPassword [stuPwd=" + stuPwd + ", stuId=" + stuId + "]"; }
} |
StuInfoDao.java:
package com.siwuxie095.dao;
import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException;
import com.siwuxie095.entity.StuInfo;
/** * 创建两个 DAO 类:StuInfoDao.java 和 StuPasswordDao.java * * 同时二者也是接口类,其实现类为: * StuInfoDaoImpl.java 和 StuPasswordDaoImpl.java * * * DAO 即 Data Access Object,数据访问对象 * * 用来封装对数据库的访问,通过它可以把数据库中的表转化为DTO类 * * * 接口定义完毕,需要编写接口相应的实现: * StuInfoDaoImpl.java 和 StuPasswordDaoImpl.java * * *接口:定义实现类的外观,即实现类的行为,相当于一份契约,根据外部应用需要的功能 *约定了实现类要实现的功能,具体的实现类除了要实现约定的功能外,还可以根据需要, *实现一些其他的功能 * *接口是系统可插拔性的保证,即只要接口不变,内部实现的变化,都不会影响到外部的应用, *使得系统更加灵活,具有更好的扩展性和维护性 * * @author siwux * */ public interface StuInfoDao { public void save(Connection conn,StuInfo stuInfo) throws SQLException; public void update(Connection conn,StuInfo stuInfo) throws SQLException; public void delete(Connection conn,StuInfo stuInfo) throws SQLException; public ResultSet get(Connection conn,StuInfo stuInfo) throws SQLException; } |
StuPasswordDao.java:
package com.siwuxie095.dao;
import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException;
import com.siwuxie095.entity.StuPassword;
public interface StuPasswordDao { public void save(Connection conn,StuPassword stuPassword) throws SQLException; public void update(Connection conn,StuPassword stuPassword) throws SQLException; public void delete(Connection conn,StuPassword stuPassword) throws SQLException; //根据stuId和stuPwd获取用户信息,返回信息为ResultSet public ResultSet get(Connection conn,StuPassword stuPassword) throws SQLException; } |
StuInfoDaoImpl.java:
package com.siwuxie095.dao.impl;
import java.sql.Connection; import java.sql.SQLException;
import com.siwuxie095.dao.StuInfoDao; import com.siwuxie095.entity.StuInfo;
import java.sql.PreparedStatement; import java.sql.ResultSet;
public class StuInfoDaoImpl implements StuInfoDao {
/** * 保存用户信息 */ @Override public void save(Connection conn, StuInfo stuInfo) throws SQLException { //PreparedStatement 是JDBC用来执行SQL查询语句的API之一 //它用来执行参数化的查询,其中问号 ? 是占位符 PreparedStatement ps=conn .prepareStatement("insert into stu_info(stu_id,stu_name,stu_sex," + "stu_academic,stu_major) values(?,?,?,?,?)"); //注意:索引从 1 开始 //将参数传入的 StuInfo类的对象stuInfo中的相关信息保存到数据库表中 ps.setString(1, stuInfo.getStuId()); ps.setString(2, stuInfo.getStuName()); ps.setString(3, stuInfo.getStuSex()); ps.setString(4, stuInfo.getStuAcademic()); ps.setString(5, stuInfo.getStuMajor()); ps.execute(); } /** * 根据指定的stuId更新用户信息 */ @Override public void update(Connection conn, StuInfo stuInfo) throws SQLException { String updateSql="update stu_info set stu_name=?,stu_sex=?,stu_academic=?," + "stu_major=? where stu_id=?"; PreparedStatement ps=conn.prepareStatement(updateSql); ps.setString(1, stuInfo.getStuName()); ps.setString(2, stuInfo.getStuSex()); ps.setString(3, stuInfo.getStuAcademic()); ps.setString(4, stuInfo.getStuMajor()); ps.setString(5, stuInfo.getStuId()); ps.execute(); }
/** * 删除指定用户信息 */ @Override public void delete(Connection conn, StuInfo StuInfo) throws SQLException { PreparedStatement ps=conn.prepareStatement("delete from stu_info where stu_id=?"); ps.setString(1, StuInfo.getStuId()); ps.execute(); }
/** * 查询用户信息 */ @Override public ResultSet get(Connection conn, StuInfo stuInfo) throws SQLException { PreparedStatement ps=conn.prepareStatement("select * from stu_info where stu_id=?"); ps.setString(1, stuInfo.getStuId()); return ps.executeQuery(); }
} |
StuPasswordDaoImpl.java:
package com.siwuxie095.dao.impl;
import java.sql.Connection; import java.sql.SQLException;
import com.siwuxie095.dao.StuPasswordDao; import com.siwuxie095.entity.StuPassword;
import java.sql.PreparedStatement; import java.sql.ResultSet;
public class StuPasswordDaoImpl implements StuPasswordDao {
public void save(Connection conn, StuPassword stuPassword) throws SQLException { String insertSql = "insert into stu_password(stu_id,stu_pwd) values(?,?)"; PreparedStatement ps = conn.prepareStatement(insertSql); ps.setString(1, stuPassword.getStuId()); ps.setString(2, stuPassword.getStuPwd()); ps.execute(); }
@Override public void update(Connection conn, StuPassword stuPassword) throws SQLException { String updateSql = "update stu_password set stu_pwd=? where stu_id=?"; PreparedStatement ps = conn.prepareStatement(updateSql); ps.setString(1, stuPassword.getStuPwd()); ps.setString(2, stuPassword.getStuId()); ps.execute(); }
@Override public void delete(Connection conn, StuPassword stuPassword) throws SQLException { String deleteSql = "delete from stu_password where stu_id=?"; PreparedStatement ps = conn.prepareStatement(deleteSql); ps.setString(1, stuPassword.getStuId()); ps.execute(); }
/** * 查询用户信息 */ @Override public ResultSet get(Connection conn, StuPassword stuPassword) throws SQLException { PreparedStatement ps = conn.prepareStatement("select * from stu_password where " + "stu_id=? and stu_pwd=?"); ps.setString(1, stuPassword.getStuId()); ps.setString(2, stuPassword.getStuPwd()); return ps.executeQuery();//直接返回查询结果 }
} |
DaoTest.java(主类):
package com.siwuxie095.test;
import java.sql.Connection;
import com.siwuxie095.dao.StuInfoDao; import com.siwuxie095.dao.StuPasswordDao; import com.siwuxie095.dao.impl.StuInfoDaoImpl; import com.siwuxie095.dao.impl.StuPasswordDaoImpl; import com.siwuxie095.entity.StuInfo; import com.siwuxie095.entity.StuPassword; import com.siwuxie095.util.ConnectionFactory;
public class DaoTest {
public static void main(String[] args) { Connection conn = null;
try { //使用ConnectionFactory来获取一个数据库连接 conn = ConnectionFactory.getInstance().makeConnection(); conn.setAutoCommit(false);//关闭事务的自动提交 StuInfoDao stuInfoDao = new StuInfoDaoImpl(); StuInfo stuInfo = new StuInfo(); stuInfo.setStuId("006"); stuInfo.setStuName("小黑"); stuInfo.setStuSex("男"); stuInfo.setStuAcademic("环境学院"); stuInfo.setStuMajor("大气学"); stuInfoDao.save(conn, stuInfo); StuPasswordDao stuPasswordDao=new StuPasswordDaoImpl(); StuPassword stuPassword=new StuPassword(); stuPassword.setStuId("006"); stuPassword.setStuPwd("006"); stuPasswordDao.save(conn, stuPassword); conn.commit();
} catch (Exception e) { System.out.println("=======捕获到SQL异常======="); e.printStackTrace(); try { conn.rollback(); System.out.println("=======事务回滚成功======="); } catch (Exception e2) { e2.printStackTrace(); }finally { try { if (conn!=null) { conn.close(); } } catch (Exception e3) { e3.printStackTrace(); } } } } } |
先创建一个连接工厂类:ConnectionFactory,用于连接数据库(单例)
再创建DTO抽象类:StuIdEntity,它的两个子类:StuInfo 和 StuPassword,
分别对应数据库的两张表:stu_info 和 stu_password
「DTO:对象与数据库表的绑定,用于转换数据」
然后创建DAO接口类:StuInfoDao 和 StuPasswordDao,定义实现类的行为:
执行 SQL 语句,实现类为:StuInfoDaoImpl 和 StuPasswordDaoImpl
「DAO:封装对数据库的访问,用于访问数据」
最后创建主类:DaoTest 进行测试
注意:高版本的 JDBC 驱动需要指明是否进行 SSL 连接
即 加上:?characterEncoding=utf8&useSSL=false
或:
即 加上:?useUnicode=true&characterEncoding=utf-8&useSSL=false
总结 JDBC 编程流程:
(1)加载驱动:加载 JDBC 驱动程序
(2)打开连接:打开一个数据库连接
(3)执行查询:创建一个会话对象,执行增删改查等操作
(4)处理结果:处理查询的结果
(5)清理环境:关闭会话,关闭连接等操作,完成资源的清理工作
关于 数据库的准备,详见本人博客的分类:来一杯Java,
里面的 JDBC编程之数据准备
本人博客(任选其一)链接:
https://www.baidu.com/s?ie=UTF-8&wd=siwuxie095
【made by siwuxie095】