数据库使用MySQL
文章目录
- 1. JDBC简介
- 2. JDBC程序访问数据库步骤
- 3. 获取数据库连接
- 3.0 导入jar包
- 3.1 Driver 接口
- 3.2 JDBC URL
- 3.3 方式1:
- 3.4 方式2:
- 3.5 方式3:
- 3.5 方式4:
- 3.6 方式5(final版):
- 连接报错:
- 1. Cause: java.sql.SQLException: Unknown initial character set index '255' received from server.
- 4. 使用Statement操作数据表的弊端【了解】
JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,(java.sql,javax.sql)使用这个类库可以以一种标准的方法、方便地访问数据库资源
JDBC驱动为对JDBC中定义的接口的实现。不同的数据库厂商,需要针对这套接口,提供不同实现。不同的实现的集合,即为不同数据库的驱动。
JDBC接口(API)包括两个层次:
JDBC API 是一系列的接口,它使得应用程序能够进行数据库连接,执行SQL语句,并且得到返回结果。Java程序员只需要面向这套接口编程即可。
【MySQL JDBC下载官网】
压缩包下载到本地后解压,在IDE项目根目录下新建lib目录
把下载的压缩包解压后的jar包复制到lib目录下
复制完成后鼠标右键jar包,添加为库
java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现
在程序中不需要直接去访问实现了 Driver 接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现
JDBC URL 用于标识一个被注册的驱动程序,驱动程序管理器通过这个 URL 选择正确的驱动程序,从而建立到数据库的连接。
JDBC URL的标准由三部分组成,各部分间用冒号分隔。
如有报错后面的解决方法可能会有帮助
@Test
public void testConnection1() throws Exception {
// 获取 Driver 驱动对象
Driver driver = new com.mysql.jdbc.Driver();
// 配置获取连接数据对象需要的信息
// url:http://localhost:8080/gmall/keyboard.jpg
// jdbc:mysql:协议
// localhost:ip地址
// 3306:默认mysql的端口号
// test:test数据库
// 字符集与数据库不一致 ?characterEncoding=utf8 设置字符集
String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8";
// 将用户名和密码封装到Properties对象中
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "123456");
// 通过驱动对象根据配置信息获取连接数据库的对象
Connection connection = driver.connect(url, info);
// 打印连接对象,查看是否连接成功
System.out.println(connection);
}
对方式一的迭代:在如下的程序中不出现第三方的api,使得程序具有更好的可移植性
@Test
public void testConnection2() throws Exception {
// 获取 Driver 驱动对象
// 使用反射
// 获取连接数据库驱动的类
Class clazz = Class.forName("com.mysql.jdbc.Driver");
// 通过连接驱动的类创建连接驱动Driver对象
Driver driver = (Driver) clazz.newInstance();
// 数据库的url
String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8";
// 连接数据库需要的用户信息配置对象
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "123456");
// 获取连接数据库的对象
Connection connection = driver.connect(url, info);
System.out.println(connection);
}
使用DriverManager替换Driver
DriverManager 类是驱动程序管理器类,负责管理驱动程序
@Test
public void testConnection3() throws Exception {
// 获取 Driver 驱动对象
// 使用反射
Class clazz = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) clazz.newInstance();
// 连接数据库的配置信息
String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8";
String user = "root";
String password = "285013";
// 通过 DriverManager 注册驱动
DriverManager.registerDriver(driver);
// 通过 DriverManager 获取连接对象
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
可以只是加载驱动,不用显示的注册驱动,因为在加载驱动时候就会进行驱动的注册。
@Test
public void testConnection4() throws Exception {
// 连接需要的三个基本信息
String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8";
String user = "root";
String password = "123456";
// 使用反射加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 相较于方式3,省略了如下操作
// Driver driver = (Driver) clazz.newInstance();
// 通过 DriverManager 注册驱动
// DriverManager.registerDriver(driver);
// 通过驱动管理获取数据库的连接
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
可以省略的原因:
在mysql的Driver实现类中,声明了如下的操作:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
将数据库连接需要的4个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接
此种方式的好处:
配置文件:
配置文件在src下,等号两边不能有空格!!!!!!
user=root
password=123456
url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8
driverClass=com.mysql.jdbc.Driver
@Test
public void testConnection5() throws Exception {
// 通过反射获取读取配置文件的输入流
InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
// 配置信息对象
Properties properties = new Properties();
properties.load(is); // 加载配置信息
// 得到配置信息
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driverClass = properties.getProperty("driverClass");
// 加载驱动
Class.forName(driverClass);
// 获取连接
Connection connection = DriverManager.getConnection(url, user, password);
System.out.println(connection);
}
Cause: java.sql.SQLException: Unknown initial character set index '255' received from server.
【解决方法博客链接】
使用Statement的弊端:
如何避免出现sql注入:只要用 PreparedStatement(从Statement扩展而来) 取代 Statement
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令
User 类:
public class User {
private String user;
private String password;
public User() {
}
public User(String user, String password) {
super();
this.user = user;
this.password = password;
}
@Override
public String toString() {
return "User [user=" + user + ", password=" + password + "]";
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
StatementTest 测试类:
public class StatementTest {
// 使用Statement的弊端:需要拼写sql语句,并且存在SQL注入的问题
//如何避免出现sql注入:只要用 PreparedStatement(从Statement扩展而来) 取代 Statement
@Test
public void testLogin() {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入用户名:");
String user = scanner.nextLine();
System.out.print("请输入密码:");
String password = scanner.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 = '"+ user +"' AND password = '"+ password +"'";
User returnUser = get(sql, User.class);
if(returnUser != 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 = StatementTest.class.getClassLoader().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;
}
}
当输入的用户名为:1' or
密码为:=1 or '1' = '1
就会造成SQL注入问题
因为此时进行字符串拼接完成后,需要执行的SQL语句变为:
SELECT user,password
FROM user_table
WHERE user = '1' or ' AND password = '=1 or '1' = '1'
判断是否成立的条件有原来的两个条件相与变为三个条件相或:
user = '1'
or ' AND password = '=1
or '1' = '1'
其中 '1' = '1'
一定成立,此时不管账号密码是否正确一定可以登录系统。
以上就是SQL注入问题。