数据库连接工具类
- 配置文件jdbc.properties 该文件存放在src目录下
##MySQL
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/hncu?useUnicode=true&characterEncoding=utf-8
username=root
password=1234
- 读取配置文件,并采用单例生成一个数据库连接对象。
package cn.hncu.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
/**
* 产生数据库连接工具
* CreateTime: 2018年9月17日 下午10:30:37
* @author 宋进宇 Email:447441478@qq.com
*/
public class ConnUtil {
private static Connection con;
static {
try {
//创建Properties对象
Properties p = new Properties();
// 通过类加载器 加载配置文件
p.load( ConnUtil.class.getClassLoader().getResourceAsStream( "jdbc.properties" ) );
//获取配置信息
String driver = p.getProperty("driver");
String url = p.getProperty("url");
String user = p.getProperty("username");
String password = p.getProperty("password");
//加载驱动
Class.forName( driver );
//获取连接
con = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
throw new RuntimeException( e.getMessage(), e);
}
}
private ConnUtil() {}
/**
* 获取数据库了连接对象
* @return 数据库连接对象
*/
public static Connection getConnection() {
return con;
}
}
在Java中实现跨库查询
很简单:给表名加个前缀,如 test.aa 就是 数据库test 中的表 aa
@Test
public void demo() throws Exception {
Connection con = ConnUtil.getConnection();
Statement st = con.createStatement();
String sql = "select * from test.aa";
st.executeQuery(sql);
}
准备数据库
下面脚本是为下面演示所需的数据库和表还有一些数据。
CREATE DATABASE hncu CHARACTER SET utf8;
USE hncu;
CREATE TABLE tb_user(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(10),
PASSWORD VARCHAR(10)
);
INSERT INTO tb_user(username,PASSWORD) VALUES('jack','1234');
INSERT INTO tb_user(username,PASSWORD) VALUES('张三','333');
INSERT INTO tb_user(username,PASSWORD) VALUES('Alice','1111');
ResultSet中的几个常用getXXX()方法
@Test
public void demo1() throws Exception {
Connection con = ConnUtil.getConnection();
Statement st = con.createStatement();
ResultSet resultSet = st.executeQuery(" select * from tb_user ");
System.out.println( "id\t用户名\t密码" );
while(resultSet.next()) {
//方式1:通过字段名获取相应的数据
int id = resultSet.getInt("id");
//方式2:通过字段的顺序获取对应的数据(以1开始)
String username = resultSet.getString(2);
//方式3:通过getObject()获取数据类型未知的数据,参数同上面两种
Object obj = resultSet.getObject(3);
System.out.println( id+"\t"+username+"\t"+obj);
}
}
Statement的三种执行SQL语句的方法
第一种: Statement.execute(sql)
该方式通吃所有SQL语句,包括:增、删、改、查,通过 st.execute(sql)的返回值判断,执行的sql语句是属于“查询” 还是“增、删、改或其他”,true:查询 ,false:增、删、改或其他。
@Test
public void demo2_1() throws Exception {
Connection con = ConnUtil.getConnection();
Statement st = con.createStatement();
String sql = "";
//增
//sql = " insert into tb_user(username,password) values('Rose','4321') ";
//删
//sql = " delete from tb_user where id = 4 ";
//改
//sql = " update tb_user set password='hncu' where username='张三' ";
//查
sql = " select * from tb_user ";
boolean boo = st.execute(sql);
if( boo ) {
ResultSet resultSet = st.getResultSet();
System.out.println( "id\t用户名\t密码" );
while(resultSet.next()) {
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
String password = resultSet.getString("password");
System.out.println( id+"\t"+username+"\t"+password);
}
}
con.close();
}
第二种: Statement.executeUpdate(sql)
该种方式只能执行 insert、delete、update,不能执行 select。
@Test
public void demo2_2() throws Exception {
Connection con = ConnUtil.getConnection();
Statement st = con.createStatement();
String sql = "";
//增
sql = " insert into tb_user(username,password) values('Rose','4321') ";
//删
//sql = " delete from tb_user where id = 5 ";
//改
//sql = " update tb_user set password='hncu' where username='张三' ";
int update = st.executeUpdate(sql); //返回值是执行后,影响表的行数
System.out.println( update );
con.close();
}
第三种: Statement.executeQuery(sql)
该种方式只能执行 select,不能执行 insert、delete、update。
@Test
public void demo2_3() throws Exception {
Connection con = ConnUtil.getConnection();
Statement st = con.createStatement();
String sql = " select * from tb_user ";
ResultSet resultSet = st.executeQuery(sql);
System.out.println( "id\t用户名\t密码" );
while(resultSet.next()) {
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
String password = resultSet.getString("password");
System.out.println( id+"\t"+username+"\t"+password);
}
con.close();
}
模拟用户注册
存在BUG版本:用户名或密码出现 '字符就挂,如 aa'bb
@Test //黑:用户名或密码出现 '字符就挂,如 aa'bb
public void regDemo() throws Exception {
Connection con = ConnUtil.getConnection();
Statement st = con.createStatement();
Scanner in = new Scanner( System.in );
System.out.println("请输入用户名:");
String username = in.nextLine();
System.out.println("请输入密码:");
String password = in.nextLine();
in.close();
//写死的sql语句
//String sql = " insert into tb_user(username,password) values('Bob','666666')";
//写活
String sql = " insert into tb_user(username,password) values('"+username+"','"+password+"')";
int update = st.executeUpdate(sql);
if( update>0 ) {
System.out.println("注册成功!!!");
}
con.close();
}
模拟用户登录
存在BUG版本:密码出现 ' or '1'='1 就可以直接登录
@Test //黑:' or '1'='1
public void loginDemo() throws Exception {
Connection con = ConnUtil.getConnection();
Statement st = con.createStatement();
Scanner in = new Scanner( System.in );
System.out.println("请输入用户名:");
String username = in.nextLine();
System.out.println("请输入密码:");
String password = in.nextLine();
in.close();
String sql = " select count(1) from tb_user where username='"+username+"' and password='"+password+"' " ;
System.out.println(sql);
ResultSet resultSet = st.executeQuery(sql);
if( resultSet.next() ) {
int i = resultSet.getInt(1);
if( i > 0 ) {
System.out.println("登录成功");
}else {
System.out.println("登录失败");
}
}
con.close();
}
无BUG版
由于使用Statement 会出现上述BUG 所以,这时候应该采用PreparedStatement类, 该对象可以通过'占位符'的方式,先预编译sql语句, 等接收到相应的数据时在通过 setxxx()来补充sql语句 ,最后再执行。
@Test //防黑:' or '1'='1
public void loginDemo2() throws Exception {
Connection con = ConnUtil.getConnection();
//使用'占位符':? 来代替真正的变化的数据的位置。
String sql = " select count(1) from tb_user where username=? and password=?";
PreparedStatement pst = con.prepareStatement(sql);
//接收用户输入
Scanner in = new Scanner( System.in );
System.out.println("请输入用户名:");
String username = in.nextLine();
System.out.println("请输入密码:");
String password = in.nextLine();
in.close();
//把用户输入的数据补充到原先占位符的位置,注意:从1开始。
pst.setString(1, username); //该方法内部把敏感字符进行转义了。
pst.setString(2, password);
ResultSet resultSet = pst.executeQuery();
if( resultSet.next() ) {
int i = resultSet.getInt(1);
if( i > 0 ) {
System.out.println("登录成功");
}else {
System.out.println("登录失败");
}
}
con.close();
}