什么是JDBC
JDBC(Java Database Connectivity),即Java数据库连接,是一种用于执行SQL语句的Java API,可以为多种关系数据库提供同一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,根据这种基准可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。总而言之,JDBC做了三件事:
1、与数据库建立连接
2、发送操作数据库的语句
3、处理结果
JDBC简单示例
下面的代码演示了如何利用JDBC从数据库中查询若干条符合要求的数据出来,使用的数据库是MySql。
1、建立一个数据库和一张表,我的习惯是在CLASSPATH底下建立一个.sql的文件用于存放sql语句
create database school; use school; create table student ( studentId int primary key auto_increment not null, studentName varchar(10) not null, studentAge int, studentPhone varchar(15) ) insert into student values(null,'Betty', '20', '00000000'); insert into student values(null,'Jerry', '18', '11111111'); insert into student values(null,'Betty', '21', '22222222'); insert into student values(null,'Steve', '27', '33333333'); insert into student values(null,'James', '22', '44444444'); commit;</div>
2、建立一个.properties文件用于存储MySql连接的几个属性。为什么要建立.properties而不在代码里面写死,由于这个并不是Java设计模式的分类,就不细讲了,只需要记住:从设计的角度看,把内容写在配置文件中永远好过把内容写死在代码中。
mysqlpackage=com.mysql.jdbc.Driver mysqlurl=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf-8 mysqlname=root mysqlpassword=root</div>
3、根据表字段建立实体类
public class Student
{
private int studentId;
private String studentName;
private int studentAge;
private String studentPhone;
public Student(int studentId, String studentName, int studentAge,
String studentPhone)
{
this.studentId = studentId;
this.studentName = studentName;
this.studentAge = studentAge;
this.studentPhone = studentPhone;
}
public int getStudentId()
{
return studentId;
}
public String getStudentName()
{
return studentName;
}
public int getStudentAge()
{
return studentAge;
}
public String getStudentPhone()
{
return studentPhone;
}
public String toString()
{
return "studentId = " + studentId + ", studentName = " + studentName + ", studentAge = " +
studentAge + ", studentPhone = " + studentPhone;
}
}
</div>
4、写一个DBConnection类专门用于向外提供数据库连接。我这里用了MySql,所以只有一个mysqlConnection,如果还用到了Oracle,当然还可以向外提供一个oracleConnection。把这些连接设为全局的可能有人会想是否会有线程安全问题,这是一个很好的问题。那因为我们只从Connection里面读取一个PreparedStatement出来,而不会去写它,只读不修改,是不会引发线程安全问题的。另外把Connection设置为static的保证了Connection在内存中只有一份,不会占多大资源,每次使用完不调用close()方法去关闭它也没事。
public class DBConnection
{
private static Properties properties = new Properties();
static
{
/** 要从CLASSPATH下取.properties文件,因此要加"/" */
InputStream is = DBConnection.class.getResourceAsStream("/db.properties");
try
{
properties.load(is);
}
catch (IOException e)
{
e.printStackTrace();
}
}
/** 这个mysqlConnection只是为了用来从里面读一个PreparedStatement,不会往里面写数据,因此没有线程安全问题,可以作为一个全局变量 */
public static Connection mysqlConnection = getConnection();
public static Connection getConnection()
{
Connection con = null;
try
{
Class.forName((String)properties.getProperty("mysqlpackage"));
con = DriverManager.getConnection((String)properties.getProperty("mysqlurl"),
(String)properties.getProperty("mysqlname"),
(String)properties.getProperty("mysqlpassword"));
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
catch (SQLException e)
{
e.printStackTrace();
}
return con;
}
}
</div>
5、建立一个工具类,用来写各种方法,专门和数据库进行交互。这种工具类最好搞成单例的,这样就不用每次去new出来了(实际上new出来也没看出来会有什么好处),节省资源
package com.xrq.test11;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class StudentManager
{
private static StudentManager instance = new StudentManager();
private StudentManager()
{
}
public static StudentManager getInstance()
{
return instance;
}
public List<Student> querySomeStudents(String studentName) throws Exception
{
List<Student> studentList = new ArrayList<Student>();
Connection connection = DBConnection.mysqlConnection;
PreparedStatement ps = connection.prepareStatement("select * from student where studentName = ?");
ps.setString(1, studentName);
ResultSet rs = ps.executeQuery();
Student student = null;
while (rs.next())
{
student = new Student(rs.getInt(1), rs.getString(2), rs.getInt(3), rs.getString(4));
studentList.add(student);
}
ps.close();
rs.close();
return studentList;
}
}
</div>
6、写个main函数去调用一下
List<Student> studentList = new ArrayList<Student>();
studentList = StudentManager.getInstance().querySomeStudents("Betty");
for (Student student : studentList)
System.out.println(student);
</div>
7、看一下运行结果,和数据库里面的一样,成功
studentId = 1, studentName = Betty, studentAge = 20, studentPhone = 00000000 studentId = 3, studentName = Betty, studentAge = 21, studentPhone = 22222222</div>
为什么要使用占位符"?"
看一下第5点,大家一定注意到了,写sql语句的时候用了"?"占位符,当然有美化代码的因素,不用占位符就要在括号里写"+"来拼接参数,如果要拼接的参数一多,代码肯定不好看,可读性不强。但是除了这个原因,还有另外一个重要的原因,就是避免一个安全问题。假设我们不用占位符写sql语句,那"querySomeStudents(String name) throws Exception"方法就要这么写:
public List<Student> querySomeStudents(String studentName) throws Exception
{
List<Student> studentList = new ArrayList<Student>();
Connection connection = DBConnection.mysqlConnection;
PreparedStatement ps = connection.prepareStatement("select * from student where studentName = '" + studentName + "'");
ResultSet rs = ps.executeQuery();
Student student = null;
while (rs.next())
{
student = new Student(rs.getInt(1), rs.getString(2), rs.getInt(3), rs.getString(4));
studentList.add(student);
}
ps.close();
rs.close();
return studentList;
}
</div>
上面的main函数一样可以获取到两条数据,但是问题来了,如果我这么调用呢:
public static void main(String[] args) throws Exception
{
List<Student> studentList = new ArrayList<Student>();
studentList = StudentManager.getInstance().querySomeStudents("' or '1' = '1");
for (Student student : studentList)
System.out.println(student);
}
</div>

