使用JDBC连接数据库
一准备
1、数据库服务是否开启
2、 连接的数据库是否是远程的
是检查远程连接的服务是否开启,或者用户是否有远程登录的权限
3、检查客户机与数据库服务器之间是否能ping通
4、准备要连接的数据库的驱动包
注意:请根据自己的数据库版本和jdk选择jar包
Oracleojdbc6.jar
SQLServer :sqljdbc4.jar
MySql:mysql-connector-java-5.1.44-bin.jar
编写BaseDao要用到的jar包
dom4j-2.1.1.jar用于xml解析
jstl.jarResult对象需要用到jstl支持
二数据库连接文件的配置
1、使用属性文件(.properties)配置
#Oracle配置
#driver=oracle.jdbc.driver.OracleDriver
#connStr=jdbc:oracle:thin:@192.168.11.111:1521:orcl
#userName=scott
#userPwd=scott
#MySql 配置
userName=root
userPwd=root
connStr=jdbc:mysql://192.168.11.111:3306/PetDB
driver=com.mysql.jdbc.Driver
#SQL Server配置
#userName=sa
#userPwd=sasa
#connStr=jdbc:sqlserver://localhost:1433;databaseName=PetDB
#driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
2、使用xml配置
DBConfig.dtd">
com.mysql.jdbc.Driver
jdbc:mysql://192.168.11.111/PetDB
root
root
三BaseDao的编写和测试
1、BaseDao的编写
packagecom.hx.basedao;
importjava.io.File;
importjava.io.FileWriter;
importjava.io.IOException;
importjava.io.InputStream;
importjava.lang.reflect.Field;
importjava.math.BigDecimal;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importjava.sql.ResultSetMetaData;
importjava.sql.Statement;
importjava.util.ArrayList;
importjava.util.HashMap;
importjava.util.List;
importjava.util.Map;
importjava.util.Properties;
importjavax.servlet.jsp.jstl.sql.Result;
importjavax.servlet.jsp.jstl.sql.ResultSupport;
importorg.dom4j.Document;
importorg.dom4j.DocumentException;
importorg.dom4j.Element;
importorg.dom4j.io.OutputFormat;
importorg.dom4j.io.SAXReader;
importorg.dom4j.io.XMLWriter;
publicclassBaseDao {
privatestaticfinalStringUSER_PWD="userPwd";
privatestaticfinalStringUSER_NAME="userName";
privatestaticfinalStringCONN_STR="connStr";
privatestaticfinalStringDRIVER="driver";
privatestaticStringdriver="";
privatestaticStringconnStr="";
privatestaticStringuserName="";
privatestaticStringuserPwd="";
static{
try{
getDBConfigByXML();
}catch(Exceptione) {
e.printStackTrace();
}
}
publicstaticvoidgetDBConfigPro() {
// 创建属性文件对象
Propertiesp=newProperties();
// 获取要读取的属性文件的输入流
// 注意属性文件的路径
// 路径只能以/开头,表示根目录
// 不能以./或../开头
// 或者其他目录开头
// 参考网址:https://blog.csdn.net/cyxinda/article/details/78254057
InputStreamis= BaseDao.class.getResourceAsStream("/DBConfig.properties");
// 获取BaseDao的路径
// System.out.println(BaseDao.class.getClassLoader().getResource("").getPath());
// 输出此代码,获取到路径,对比配置文件
try{
// 把流加载到属性文件,读取对象
p.load(is);
}catch(Exceptionex) {
ex.printStackTrace();
}finally{
try{
is.close();
}catch(IOExceptione) {
e.printStackTrace();
}
}
driver=p.getProperty(DRIVER);
connStr=p.getProperty(CONN_STR);
userName=p.getProperty(USER_NAME);
userPwd=p.getProperty(USER_PWD);
}
publicstaticvoidgetDBConfigByXML()throwsException {
SAXReaderreader=newSAXReader();
// 通过read方法读取一个文件 转换成Document对象
// System.out.println(BaseDao.class.getClassLoader().getResource("OracleConn.xml").getPath());
/// E:/WorkSpace/Utils/bin/OracleConn.xml
Documentdoc=reader.read(newFile(BaseDao.class.getClassLoader().getResource("DBConfig.xml").getPath()));
// 获取根节点
Elementroot=doc.getRootElement();// configuration
// 获取根节点的子节点
Listes=root.elements();
for(Elemente:es) {
if(e.getName().equals(DRIVER)) {
driver=e.getText().trim();
// System.out.println(driver);
}elseif(e.getName().equals(CONN_STR)) {
connStr=e.getText().trim();
}elseif(e.getName().equals(USER_NAME)) {
userName=e.getText().trim();
}elseif(e.getName().equals(USER_PWD)) {
userPwd=e.getText().trim();
}
}
}
/**
* 获取数据库连接的方法
*
*@return数据库连接对象
*/
publicstaticConnection getConn() {
// 创建连接对象
Connectionconn=null;
try{
// 1、加载驱动
Class.forName(DRIVER);
// 2、获取连接
conn= DriverManager.getConnection(CONN_STR,USER_NAME,USER_PWD);
}catch(Exceptionex) {
ex.printStackTrace();
}
returnconn;// 返回连接对象
}
/**
* 关闭所有资源
*
*@paramconn 连接对象
*@paramstmt 命令对象
*@paramrs 结果集
*/
publicstaticvoidcloseAll(Connectionconn, Statementstmt, ResultSetrs) {
try{
if(rs!=null) {
rs.close();
}
}catch(Exceptionex) {
ex.printStackTrace();
}
try{
if(stmt!=null) {
stmt.close();
}
}catch(Exceptionex) {
ex.printStackTrace();
}
try{
if(conn!=null) {
conn.close();
}
}catch(Exceptionex) {
ex.printStackTrace();
}
}
/**
* 参数赋值的方法
*
*@parampstmt 命令对象
*@paramparams 参数数组
*@throwsException
*/
publicstaticvoidsetParams(PreparedStatementpstmt, Object[]params)throwsException {
// 判断sql语句是否有参数
if(params!=null&¶ms.length> 0) {
// 循环给sql语句的参数赋值
for(inti= 0;i
pstmt.setObject(i+ 1,params[i]);
}
}
}
/**
* 执行增、删、改sql语句的通用方法
*
*@paramsql 要执行的sql语句
*@paramparamssql语句需要的参数,为null时表示sql语句没有参数
*@return受影响的行数
*@throwsException
*/
publicstaticintupdate(Stringsql, Object[]params) {
introw= 0;// 保存执行后受影响的行数
Connectionconn=null;// 连接对象
PreparedStatementpstmt=null;// 命令对象,预编译
try{
// 1、获取连接对象(调用ConnectionUtil类中的getConn()方法)
conn=getConn();
// 2、获取命令对象
pstmt=conn.prepareStatement(sql);
// 判断sql语句是否需要设置参数
if(params!=null) {
setParams(pstmt,params);
}
// 3、执行sql语句
row=pstmt.executeUpdate();
}catch(Exceptionex) {
ex.printStackTrace();
}finally{
// 关闭资源
closeAll(conn,pstmt,null);
}
returnrow;
}
/**
* 查询的通用方法
*
*@paramsql 要执行的sql语句
*@paramparamssql语句需要的参数数组
*@returnresult对象
*/
publicstaticResult getResult(Stringsql, Object[]params) {
Connectionconn=null;// 连接对象
PreparedStatementpstmt=null;// 命令对象
ResultSetrs=null;// 结果集
Resultresult=null;
try{
// 获取连接对象
conn=getConn();
// 根据连接对象获取命令对象
pstmt=conn.prepareStatement(sql);
// 判断sql语句是否需要设置参数
if(params!=null) {
setParams(pstmt,params);
}
// 执行命令
rs=pstmt.executeQuery();
// 把结果集转换为result对象
result= ResultSupport.toResult(rs);
}catch(Exceptionex) {
ex.printStackTrace();
}finally{
// 关闭资源
closeAll(conn,pstmt,rs);
}
returnresult;
}
/**
*-查询的通用方法-这个方法容易报错
*
*@paramsql 要执行的sql语句
*@paramparamssql语句需要的参数数组
*@returnresult对象
*/
publicstaticList> queryByResultSet(Stringsql, Object[]params, Class>clz) {
Listlist=null;// 保存查询结果
Connectionconn=null;// 连接对象
PreparedStatementpstmt=null;// 命令对象
ResultSetrs=null;// 结果集
try{
// 获取连接对象
conn=getConn();
// 根据连接对象获取命令对象
pstmt=conn.prepareStatement(sql);
// 判断sql语句是否需要设置参数
if(params!=null) {
setParams(pstmt,params);
}
// 执行命令
rs=pstmt.executeQuery();
// 判断是否存在记录
if(rs!=null) {// 有数据
// rs.next()
// 存在记录rs就要向上移一条记录 因为rs.next会滚动一条记录了
// rs.previous();
// 在执行while 循环
list=newArrayList();
while(rs.next()) {
// 结果集的元数据,结果集是由数据库表中一行行数据组成的
// 这里获取的是一行数据
ResultSetMetaDatametaData=rs.getMetaData();
intcount=metaData.getColumnCount();// 获取总列数;
// System.out.println("总列数"+count);
Objectobj=clz.newInstance();// 获取类对象的实例;
for(inti= 0;i
Objectvalue=rs.getObject(i+ 1);// 获取对应列所对应的字段值
// System.out.println("对应列所对应的字段值"+value);
Stringcolname=metaData.getColumnName(i+ 1).toLowerCase();// 获取对应列名;
// System.out.println("列名:"+colname);
// oracle 不管你建表时字段是大写还是小写,它一律帮你转换成大写
// 建议所有java类的属性都小写
// ①没有对应字段;②属性为私有时获取Field用的方法不是getDeclaredField。否则会报错
Fieldfield=clz.getDeclaredField(colname);// 通过列名获取到字段对象,就是我们所说的属性;
field.setAccessible(true);
// 此处调用了Field类的set方法,就是给封装类对象所对应的字段赋值操作,
// 这样数据表对应的封装类的对象类就有值了,相当于查询到了理想的结果。
// 判断字段的数据类型
// Oracle 中 number类型 通过ResultSet 的 getObject() 返回的是 BigDecimal 类型
if(valueinstanceofBigDecimal) {
// System.out.println("bigdecimal");
intnum= ((BigDecimal)value).intValue();
field.set(obj,num);
}else{
field.set(obj,value);// 将指定对象变量上此 Field 对象表示的字段设置为指定的新值
}
}
// 因为考虑到查询的结果不止一条,用集合进行操作
// 然后返回该结果集对象
list.add(obj);
}
}
}catch(Exceptionex) {
ex.printStackTrace();
}finally{
// 关闭资源
closeAll(conn,pstmt,rs);
}
returnlist;
}
/**
* 查询的通用方法 将表中的一行数据保存到一个map对象中,key为列(字段)的下标,value为该列(字段)的值 返回保存map的泛型集合
*
*@paramsql 要做执行的sql语句
*@paramparams SQL语句需要的参数
*@return
*/
publicstaticList QueryByResultSet(Stringsql, Object[]params) {
Connectionconn=null;
PreparedStatementpstmt=null;
ResultSetrs=null;
try{
// 1.获取conn
conn=getConn();
// 2.获取Statement
pstmt=conn.prepareStatement(sql);
if(params!=null) {
setParams(pstmt,params);
}
// 4.执行查询,得到ResultSet
rs=pstmt.executeQuery(sql);
// 5.处理ResultSet
Listlist=newArrayList();
ResultSetMetaDatametaData=rs.getMetaData();
intcolumnCount=metaData.getColumnCount();
while(rs.next()) {
MaprowData=newHashMap();
for(inti= 1;i
rowData.put(metaData.getColumnName(i).toLowerCase(),rs.getObject(i));
}
list.add(rowData);
}
returnlist;
}catch(Exceptione) {
e.printStackTrace();
}finally{
// 6.关闭数据库相应的资源
closeAll(conn,pstmt,rs);
}
returnnull;
}
}
测试
在数据库创建表,没有数据库的先创建数据库
在项目中创建表对应的类
接下来进行单元测试
1.1在Oracle服务器 的ORCL中创建表
/*
id;神兽的编号
masterId;所属的世界之主编号
name;神兽的昵称
health;健康值
lover;亲密度
type;类型
grade;// 神兽青龙所特有的
*/
droptableDragon;
createtabledragon(
idnumber(5)primarykeynotnull,
masteridnumber(5) ,
namevarchar2(10) ,
healthnumber(3),
lovernumber(3),
typevarchar2(10),
gradevarchar(10)
)
--插入数据
insertinto(id,masterid,name,health,lover,type,grade)values()
--创建序列
createsequencedragonid_sequ
incrementby1
startwith10000
nomaxvalue
nocycle
cache10;
--查询表
select*fromdragon
--删除表
droptabledragon
1.2在SQL Server 中创建PetDB数据库 和Dragon表
--创建PetDB数据库
createdatabaseStudentDB
onprimary--主文件组
(
--数据库文件的逻辑名称,不能重复
name='PetDB',
--数据库物理文件名(绝对路径)
filename='E:\PetDB.mdf',
--数据库文件初始大小
size=10MB,
--数据文件增长量
filegrowth=1MB
)
logon
(
--日志文件的逻辑名称,不能重复
name='PetDB_log',
--日志物理文件名(绝对路径)
filename='E:\PetDB_log.ldf',
--日志文件初始大小
size=3MB,
--日志文件增长量
filegrowth=1MB
)
go
--创建Dragon表
createtableDragon(
idnumeric(5,0)identity(1,1)primarykeynotnull,
masteridnumeric(5,0),
namevarchar(10),
healthnumeric(3,0),
lovernumeric(3,0),
typevarchar(10),
gradevarchar(10)
)
1.3在MySql中创建PetDB数据库 和Dragon表
创建数据库
CREATE DATABASE `PetDB`
创建表
CREATE TABLE `dragon` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`masterId` int(11) DEFAULT NULL,
`name` varchar(45) DEFAULT NULL,
`health` int(11) DEFAULT NULL,
`lover` int(11) DEFAULT NULL,
`type` varchar(45) DEFAULT NULL,
`grade` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`))
ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf
1.4在java项目中创建Dragon类
packagecom.hx.entity;
publicclassDragon {
/**
* 神兽的编号
*/
privateintid;
/**
* 所属的世界之主编号
*/
privateintmasterid;
/**
* 神兽的昵称
*/
privateStringname;
/**
* 健康值
*/
privateinthealth;
/**
* 亲密度
*/
privateintlover;
/**
* 类型
*/
privateStringtype;
/**
* 等级
*/
privateStringgrade;// 神兽青龙所特有的
publicintgetId() {
returnid;
}
publicvoidsetId(intid) {
this.id=id;
}
publicintgetMasterid() {
returnmasterid;
}
publicvoidsetMasterId(intmasterId) {
this.masterid=masterId;
}
publicString getName() {
returnname;
}
publicvoidsetName(Stringname) {
this.name=name;
}
publicintgetHealth() {
returnhealth;
}
publicvoidsetHealth(inthealth) {
this.health=health;
}
publicintgetLover() {
returnlover;
}
publicvoidsetLover(intlover) {
this.lover=lover;
}
publicString getType() {
returntype;
}
publicvoidsetType(Stringtype) {
this.type=type;
}
publicString getGrade() {
returngrade;
}
publicvoidsetGrade(Stringgrade) {
this.grade=grade;
}
@Override
publicString toString() {
return"Dragon [id="+id+", masterId="+masterid+", name="+name+", health="+health+", lover="
+lover+", type="+type+", grade="+grade+"]";
}
}
1.5开始测试
测试比较简单只测了查询
有兴趣的话可以更改配置文件测试不同数据库之间的连接,和对表的其他操作
packagecom.hx.test;
importstaticorg.junit.Assert.*;
importjava.io.File;
importjava.io.IOException;
importjava.util.HashMap;
importjava.util.List;
importjava.util.Map;
importjava.util.Map.Entry;
importjava.util.Set;
importorg.junit.Test;
importcom.hx.basedao.BaseDao;
importcom.hx.entity.Dragon;
publicclassTestJDBC {
publicstaticvoidmain(String[]args)throwsIOException {
test();
}
@Test
publicstaticvoidtest() {
Stringsql="select * from dragon";
ListdList=(List) BaseDao.queryByResultSet(sql,null, Dragon.class);
for(Dragondragon:dList) {
System.out.println(dragon.toString());
}
}
@Test
publicstaticvoidtest2() {
Stringsql="select * from dragon";
Listlist= BaseDao.QueryByResultSet(sql,null);
for(Mapm:list) {
System.out.println(m.get("id"));
}
}
}