java代码中操作数据库。(本文以MySQL为例)
操作通常分6步:
1.加载数据库驱动
2.建立数据库连接对象
3.创建执行SQL的语句对象
4.执行SQL语句
5.处理结果
6.释放数据库资源
数据库厂商会实现符合自己的数据库特点的数据库驱动程序。
常见数据库产品驱动加载方式如下:
Mysql
Class.forName("com.mysql.jdbc.Driver");
Oracle
Class.forName("oracle.jdbc.driver.OracleDriver");
SQLServer
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
实际操作:
本文使用的是MySQL,首先下载一个MySQL的jdbc的jar文件。本文使用的是mysql-connector-java-5.1.41-bin.jar(可自行官网或网络下载并导入)
封装:
private static String className,url,user,password;
/**
* 1.加载驱动,静态代码块,只执行一次
*/
static {
try {
// 1.1.从配置文件中初始化数据库连接参数
Properties pops = new Properties();
pops.load(UtilsJDBC.class.getResourceAsStream("/jdbc.properties"));
className = pops.getProperty("className");
url = pops.getProperty("url");
user = pops.getProperty("user");
password = pops.getProperty("password");
// 1.2.加载驱动
Class.forName(className);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 建立连接
* @return 连接对象
*/
private static Connection getConn() {
Connection conn = null;
try {
conn = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
考虑到多人同时操作数据库的问题,于是并没有给静态参数url、user、password赋值。而是通过使用配置文件jdbc.properties来封装。然后从配置文件中取出数据初始化。
下面到了创建SQL语句对象
常用的有Statement对象和PreparedStatement对象
Statement对象通过
Statement stmt = conn.createStatement();
PreparedStatement对象通过
String sql = “select * from students where name = ? and sex = ?”;
PreparedStatement ps = conn.preparedStatement(sql);
ps.setString(1,”张三”);
ps.setString(2,”女”);
此处,参数sql可以带有占位符。
Statement对象或者PreparedStatement对象调用executeXxx()方法将SQL语句发送到数据库管理系统,数据库管理系统执行完毕之后会有结果返回,不同类型的sql语句以及不同的executeXxx()方法返回的结果都不相同,那么对结果的处理方式也不各不相同。
Statement类型语句对象的执行
boolean b = stmt.execute(sql);//执行任何sql语句
int I = stmt.executeUpdate(sql);//执行增删改SQL语句
ResultSet rs = stmt.executeQuery(sql);//执行查询语句
PreparedStatement类型语句对象的执行
boolean b = ps.execute();//执行任何类型sql语句
int I = ps.executeUpdate();//执行增删改类型sql语句
ResultSet rs = ps.executeQuery();//执行查询语句
综上,可以看出增删改,返回的是sql语句在数据库中响应的行数;而查询是返回的结果集合。所以我们可写2个封装方法来区分。
另外,
·如使用createStatement,则需要配合使用executeUpdate(sql)方法,此处传入的sql不可使用占位符;
·如使用preparedStatement(sql),则需要配合使用executeUpdate()方法,此处传入的sql可使用占位符;
··又需要对sql使用占位符或不使用占位符来进行区分。或者写重载方法。
此处,以使用preparedStatement(sql)为例,传入可变参数来避免重载,并优化使用占位符的操作
/**
* 增删改
* @param sql sql增删改语句,可含占位符?
* @param args 如使用占位符,则对占位符释义
* @return 相应数据库响应行数
*/
static public int updata(String sql,Object...args){
Connection conn = null;
PreparedStatement ps=null;
int rows = 0;
try {
conn=getConn();
ps=conn.prepareStatement(sql);
//逐个解释占位符,占位符索引从1计数,数组索引从0计数
if(args!=null && args.length>0){
for(int i=0;i0) {
System.out.println("操作成功");
}else {
System.out.println("操作失败");
}
return rows;
}
/**
* 查询
* 多表查询时,请使用别名来区分相同的列名
* @param sql sql查询语句,不含占位符?
* @param obj 占位符释义
* @return 结果集封装的list集合
*/
public static List
最后,关闭资源。当然,上述方法中已经在执行完SQL操作之后就调用了此方法对资源进行了关闭
/**
* 关闭资源
* @param res 结果集
* @param stmt 语句
* @param conn 连接
* @throws SQLException
*/
private static void close(ResultSet res, Statement stmt, Connection conn){
try {
if (res != null) {
res.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
在上述的查询方法中,对结果集进行了处理,把结果集放入了list集合中。
这样做的原因是,在处理结果集之前,不能关闭资源。否则就无法对结果集进行处理。
而在查询后,把结果放入list之后,就立即关闭了资源。而对查询结果的处理可以通过对list的操作来执行。
这样做符合Connection的使用原则,即尽量晚创建,尽可能早释放,因为数据库的连接很有限,如果不及时释放将导致系统崩溃