JDBC 速查手册
发布于: 2021 年 02 月 14 日
JDBC URL
JDBC URL 格式
jdbc:mysql://主机名称:mysql服务端口号(默认为3306)/数据库名称?参数1=值1&参数2=值2
复制代码
如果 JDBC 程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集
jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
复制代码
也可以用“属性名=属性值”方式告诉数据库
jdbc:mysql://localhost:3306/test?user=root&password=123456
复制代码
获取连接
注意:jar 包版本要和 MySQL 版本匹配,否则会连接不上。
方式一
直接使用第三方数据库的 API。
@Test
public void testConnection1() throws Exception {
// 获取 Driver 实现类对象
Driver driver = new com.mysql.jdbc.Driver();
// test:test数据库
String url = "jdbc:mysql://localhost:3306/test";
// 将用户名和密码封装在 Properties 中
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "abc123");
Connection conn = driver.connect(url, info);
System.out.println(conn);
}
复制代码
方式二
不使用第三方的 API,使用反射实例化 Driver
,体现了面向接口编程的思想,使得程序具有更好的可移植性。
@Test
public void testConnection2() throws Exception {
// 1. 获取 Driver 实现类对象:使用反射
Class clazz = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) clazz.newInstance();
// 2. 提供要连接的数据库
String url = "jdbc:mysql://localhost:3306/test";
// 3. 提供连接需要的用户名和密码
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "abc123");
// 4. 获取连接
Connection conn = driver.connect(url, info);
System.out.println(conn);
}
复制代码
方式三
使用 DriverManager
替换 Driver
。
@Test
public void testConnection3() throws Exception {
// 1. 获取 Driver 实现类的对象
Class clazz = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) clazz.newInstance();
// 2. 提供另外三个连接的基本信息:
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "abc123";
// 注册驱动
DriverManager.registerDriver(driver);
// 获取连接
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
}
复制代码
方式四
可以只是加载驱动,不用显式地注册驱动了。
@Test
public void testConnection4() throws Exception {
// 1. 提供三个连接的基本信息:
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "abc123";
// 2. 加载 Driver
Class.forName("com.mysql.jdbc.Driver");
// 3.获取连接
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
}
复制代码
之所以可以只加载驱动,而不用显式地注册驱动,是因为在 MySQL 的 Driver
实现类中,存在如下的静态代码块:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
复制代码
方式五-最终版
将数据库连接需要的 4 个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接。这种方式的好处是:
实现了数据与代码的分离,即实现了解耦
如果需要修改配置文件信息即可,可以避免程序重新打包
public class ConnectionTest {
@Test
public void getConnection5() throws Exception{
// 1. 读取配置文件中的 4 个基本信息
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
// 2. 加载驱动
Class.forName(driverClass);
// 3. 获取连接
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
}
}
复制代码
src/jdbc.properties
文件内容如下:
user=root
password=abc123
url=jdbc:mysql://localhost:3306/test
driverClass=com.mysql.jdbc.Driver
复制代码
注意:在 .properties
文件中,=
左右不要有空格。
执行 SQL 语句
Statement
使用 Statement 的弊端:需要拼写 SQL 语句,并且存在 SQL 注入的问题。
public class StatementTest {
@Test
public void testLogin() {
Scanner scan = new Scanner(System.in);
System.out.print("用户名:");
String userName = scan.nextLine(); // 这里之所以用 nextLine(),而不是 next() 方法,是因为要从标准输入中读取:"1' OR "和"=1 OR '1' = '1'"
System.out.print("密码:");
String password = scan.nextLine();
// SELECT user, password FROM user_table WHERE USER = '1' OR ' AND PASSWORD = '=1 OR '1' = '1';
String sql = "SELECT user, password FROM user_table WHERE USER = '" + userName + "' AND PASSWORD = '" + password
+ "'";
User user = get(sql, User.class);
if (user != null) {
System.out.println("登陆成功!");
} else {
System.out.println("用户名或密码错误!");
}
}
// 使用Statement实现对数据表的查询操作
public <T> T get(String sql, Class<T> clazz) {
T t = null;
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
// 1. 加载配置文件
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
// 2. 读取配置信息
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
// 3. 加载驱动
Class.forName(driverClass);
// 4. 获取连接
conn = DriverManager.getConnection(url, user, password);
st = conn.createStatement();
rs = st.executeQuery(sql);
// 获取结果集的元数据
ResultSetMetaData rsmd = rs.getMetaData();
// 获取结果集的列数
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
t = clazz.newInstance();
for (int i = 0; i < columnCount; i++) {
// //1. 获取列的名称
// String columnName = rsmd.getColumnName(i+1);
// 1. 获取列的别名
String columnName = rsmd.getColumnLabel(i + 1);
// 2. 根据列名获取对应数据表中的数据
Object columnVal = rs.getObject(columnName);
// 3. 将数据表中得到的数据,封装进对象
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);
field.set(t, columnVal);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭资源
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return null;
}
}
复制代码
划线
评论
复制
发布于: 2021 年 02 月 14 日阅读数: 29
版权声明: 本文为 InfoQ 作者【jiangling500】的原创文章。
原文链接:【http://xie.infoq.cn/article/296722491fa4a7cf91eb6fe75】。文章转载请联系作者。
jiangling500
关注
万丈高楼平地起,勿在浮沙筑高台! 2019.12.17 加入
一名IT从业者,熟悉Linux下C/C++,了解MySQL、Java等。
评论