目录
一.Statement
将user.sql导入baizhan数据库中
2.1 操作和访问数据库
数据库连接被用于向数据库服务器发送命令和 SQL 语句,并接受数据库服务器返回的结果。其实一个数
据库连接就是一个Socket连接。
在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:
- Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。
- PreparedStatement:SQL 语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句。
- CallableStatement:用于执行 SQL 存储过程。
2.2 Statement使用
导入user.sql数据
调用Connection对象的createStatement()方法创建Statement对象,
调用以下方法执行SQL语句
int execute(String sql); //执行insert、update、delete操作
ResultSet executeQuery(String sql); //执行查询操作
执行insert
处理异常快捷键:键盘按下Alt+Enter
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.Scanner;
public class Statement_test {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
//1.读取配置文件中4个基本信息
InputStream is=Java_test3.class.getClassLoader().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);
//获取Statement对象
Statement statement=conn.createStatement();
Scanner in=new Scanner(System.in);
System.out.println("请输入用户名");
String username=in.next();
System.out.println("请输入密码");
String userpassword=in.next();
//拼接sql
String sql="insert into user(username,userpassword) values('"+username+
"','"+userpassword+"')";
//执行sql
statement.execute(sql);
//关闭资源
statement.close();
conn.close();
}
}
二.ResultSet
2.3 ResultSet
ResultSet 对象具有指向其当前数据行的指针。最初,指针被置于 第一行之前 。 next 方法将指针移
动到下一行;因为该方法在 ResultSet 对象中没有下一行时返回 false ,所以可以在 while 循环中使
用它来迭代结果集。
默认的 ResultSet 对象仅有一个向前移动的指针。因此,只能迭代它一次,并且只能按从第一行到
最后一行的顺序进行。
ResultSet 接口提供用于从当前 t 行检索列值的获取方法( getBoolean 、 getLong 等)。可以使用列
的 索引编号 或列的 名称 检索值。 一般情况下,使用列索引较为高效。列从 1 开始编号。 为了获得最
大的可移植性,应该按从左到右的顺序读取每行中的结果集列,而且每列只能读取一次。
ResultSet 内存结构
执行select
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class Statement_test {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
//1.读取配置文件中4个基本信息
InputStream is=Java_test3.class.getClassLoader().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);
//获取Statement对象
Statement statement=conn.createStatement();
String sql="select * from user";
//执行sql查询,并将结果集返回
ResultSet rs=statement.executeQuery(sql);
//遍历rs获取所有结果
while(rs.next()){
//可以用列名,也可以用列索引,列索引更高效
System.out.println(rs.getString("username")+"_"+
rs.getString(3));
}
//关闭资源
statement.close();
conn.close();
}
}
使用 Statement 的弊端:
- 存在字符串拼接操作,繁琐。
- 存在SQL注入问题。
三.PreparedStatement
- PreparedStatement接口继承Statement
- PreparedStatement是预编译的,比Statement速度快
- 调用Connection对象的preparedStatement(String sql)方法获取PreparedStatement对象
- 调用以下方法执行SQL语句
int executeUpdate(); //执行insert、update、delete操作
Resultset executeQuery(); //执行查询操作
3.1 PreparedStatement添加
1. 创建 PreparedStatement 对象
String sql = "insert into user(username,userpassword) values(?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
PreparedStatement 对象所代表的 SQL 语句中的参数用问号 (?) 来表示,调用 PreparedStatement 对
象的 setXxx() 方法来设置这些参数。
2. 填充占位符
ps.setString(1,"admin6");
ps.setString(2,"123456");
setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值。
注 :
- 目前是设置String,所以使用setString方法。
- setString方法会自动给参数携带引号,该语句执行过程
insert into user(username,userpassword) values('admin6','123456')
3. 执行添加
ps . executeUpdate ();
4. 关闭资源
ps . close ();
conn . close ();
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class Statement_test {
public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
//1.读取配置文件中4个基本信息
InputStream is=Statement_test.class.getClassLoader().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);
//获取PreparedStatement对象
String sql="insert into user(username,userpassword)values(?,?)";
PreparedStatement ps=conn.prepareStatement(sql);
ps.setString(1,"admin6");
ps.setString(2,"123456");
ps.executeUpdate();
//关闭资源
ps.close();
conn.close();
}
}
3.2 JDBCUtils封装数据库连接与释放
为了统一对 Connection 资源的管理及使用,创建 JDBCUtils 工具类,实现对数据库的连接与释放进行统一管理。
不需要创建对象就可以使用的工具类,所以类中的方法全部是静态方法。这样等再写代码时,就不用每次都写一堆建立连接的代码,直接调JDBCUtils类的函数就行了。
数据库连接 :
释放连接:
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtils {
//获取数据库连接函数
public static Connection getConnection() throws IOException, ClassNotFoundException, SQLException {
//1.读取配置文件中4个基本信息
InputStream is=Statement_test.class.getClassLoader().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);
return conn;
}
//释放连接函数
//PreparedStatement是Statement的子类,
// 所以形参是Statement类型可接受PreparedStatement或Statement的实参
public static void close(Connection conn, Statement statement) throws SQLException {
if (conn!=null){
conn.close();
}
if (statement!=null){
statement.close();
}
}
}
3.3 PreparedStatement修改
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class PreparedStatement_test {
public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException {
//1.获取连接并创建PreparedStatement对象
Connection conn=JDBCUtils.getConnection();
String sql="update user set username = ? where id= ?";
PreparedStatement ps=conn.prepareStatement(sql);
//2.填充占位符
ps.setObject(1,"admintest");
ps.setInt(2,1);
//3.执行修改
ps.executeUpdate();
//4.关闭资源
JDBCUtils.close(conn,ps);
}
}
3.4 PreparedStatement通用增删改
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class PreparedStatement_test {
public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException {
String sql="delete from user where id = ? or id = ?";
//删除id为1或2的数据行
update(sql,1,2);
}
//通用增删改操作
//因为不确定是几个参数,所以用Object ...args
public static void update(String sql,Object ...args) throws SQLException, IOException, ClassNotFoundException {
Connection conn=null;
PreparedStatement ps=null;
//1.获取数据库连接
conn=JDBCUtils.getConnection();
//2.预编译sql语句,返回PreparedStatement的实例
ps=conn.prepareStatement(sql);
//3.填充占位符
for (int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
//4.执行
ps.executeUpdate();
//5.资源的关闭
JDBCUtils.close(conn,ps);
}
}
3.5 PreparedStatement查询
import java.io.IOException;
import java.sql.*;
public class PreparedStatement_select {
public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException {
//非通用查询方法
//连接数据库
// Connection conn=JDBCUtils.getConnection();
// String sql="select * from user";
// //预编译
// PreparedStatement ps=conn.prepareStatement(sql);
// //结果集
// ResultSet rs=ps.executeQuery();
// while(rs.next()){
// System.out.println(rs.getString("username")+"_"+
// rs.getString("userpassword"));
// }
// rs.close();
// JDBCUtils.close(conn,ps);
String sql="select * from user where id < ?";
query(sql,6);
}
//通用查询操作
public static void query(String sql,Object ...args) throws SQLException, IOException, ClassNotFoundException {
Connection conn=null;
PreparedStatement ps=null;
//1.获取数据库连接
conn=JDBCUtils.getConnection();
//2.预编译sql语句,返回PreparedStatement的实例
ps=conn.prepareStatement(sql);
//3.填充占位符
for (int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]+" ");
}
System.out.println();
//4.执行
ResultSet rs=ps.executeQuery();
//获取结果集元数据(可通过元数据获得返回数据的一些信息,比如列数)
ResultSetMetaData rsmd=rs.getMetaData();
//通过ResultSetMetaData获取结果集中的列数
int columnNum=rsmd.getColumnCount();
while(rs.next()){
//根据列数,通过rs.getObject方法+索引获取列的值
for (int i=0;i<columnNum;i++){
System.out.print(rs.getObject(i+1)+" ");
}
System.out.println();
}
//5.资源的关闭
JDBCUtils.close(conn,ps);
}
}
四.ORM编程思想
对象关系映射 (英语: Object Relational Mapping ,简称 ORM ,或 O/RM ,或 O/R mapping )
- 一个数据表对应一个JAVA类
- 表中的一条记录对应JAVA类的一个对象
- 表中的一个字段(列)对应JAVA类的一个属性(字段)
Java 典型的 ORM 框架中有
- hibernate:全自动的框架,强大、复杂、笨重、学习成本较高
- Mybatis:半自动的框架(懂数据库的人 才能操作) 必须要自己写sql
- JPA:JPA全称Java Persistence API、JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,是Java自带的框架
针对 user 表通用查询设计
根据 user 表设计实体类 User。
快速生成JavaBean方法:鼠标右键编辑器,选择“Generate”,也可以直接按Alt+Insert快捷键,选择即可。
User.java:
public class User {
private Integer id;
private String username;
private String userpassword;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpassword() {
return userpassword;
}
public void setUserpassword(String userpassword) {
this.userpassword = userpassword;
}
}
import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class PreparedStatement_QRM {
public static void main(String[] args) throws ClassNotFoundException, SQLException, NoSuchFieldException, IllegalAccessException, IOException {
String sql="select * from user where id < ?";
List<User> users=queryUser(sql,6);
System.out.println();
}
public static List<User> queryUser(String sql,Object ...args) throws SQLException, IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Connection conn=null;
PreparedStatement ps=null;
List<User> users=new ArrayList<>();
//1.获取数据库的连接
conn=JDBCUtils.getConnection();
//2.预编译sql语句,返回PreparedStatement的实例
ps=conn.prepareStatement(sql);
//3.填充占位符
for (int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
//4.执行
ResultSet rs=ps.executeQuery();
//获取结果集元数据
ResultSetMetaData rsmd=rs.getMetaData();
//通过ResultSetMetaData获取结果集中的列数
int columnNum=rsmd.getColumnCount();
while(rs.next()){
//创建User对象,用于保存每行数据
User u=new User();
//处理结果集中每一行的每一列,将每列的值保存到user对象中对应的属性中
for (int i=0;i<columnNum;i++){
//获取该列的值
Object columnValue=rs.getObject(i+1);
String columnName=rsmd.getColumnName(i+1);
//通过反射给user对象的columnName字段赋值为columnValue
// 获取该字段相关属性,类属性名和数据库表的属性是一样的
Field field = u.getClass().getDeclaredField(columnName);
//提升权限
field.setAccessible(true);
// 赋值
field.set(u,columnValue);
}
//将赋值后的user对象,添加进list
users.add(u);
}
//5.资源的关闭
JDBCUtils.close(conn,ps);
return users;
}
}
在System.out.println();处打个断点,右键Debug运行,查看users,果然已经被赋了数据库里的值。
五.用户登录功能
准备工作:在baizhan数据库中导入account.sql
1 业务介绍
1.1 业务需求
模拟用户登录功能实现。
1.2 业务描述
程序运行的时候,提供一个输入的入口,可以让用户输入账号和密码,用户输入之后,提交信息, JAVA
程序收集到用户信息,连接数据库验证用户名和密码是否合法。
合法:显示登录成功
不合法:显示登录失败
1.3 数据表准备
需要提供一张 Account 数据表,其中包含用户 id 、用户账号、用户密码、用户昵称。
导入 account.sql
2 登录界面初始化
初始化方法
3 登录实现
既然要访问数据库,将 JDBCUtils 引入该项目
Account 实体类
public class Account {
private Integer userid;
private String useraccount;
private String username;
private String userpassword;
//Alt+Insert快捷键生成get和set方法(或者右键Gennerate)
public Integer getUserid() {
return userid;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public String getUseraccount() {
return useraccount;
}
public void setUseraccount(String useraccount) {
this.useraccount = useraccount;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpassword() {
return userpassword;
}
public void setUserpassword(String userpassword) {
this.userpassword = userpassword;
}
}
Login.java:
import com.hbb.jdbc.JDBCUtils;
import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.*;
public class login {
public static void main(String[] args) throws ClassNotFoundException, SQLException, IOException, IllegalAccessException, NoSuchFieldException {
Map<String,String> userLoginInfo = initUI();
System.out.println(login(userLoginInfo)?"登陆成功":"登录失败");
}
//登陆界面初始化从
public static Map<String,String> initUI(){
Scanner sc=new Scanner(System.in);
System.out.println("请输入账号:");
String account=sc.next();
System.out.println("请输入密码:");
String password=sc.next();
Map<String,String> userLoginInfo =new HashMap<>();
userLoginInfo.put("account",account);
userLoginInfo.put("password",password);
return userLoginInfo;
}
//针对account表实现通用查询,返回一个查询对象列表
public static List<Account> queryAccount(String sql,Object ...args) throws SQLException, IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
List<Account> accounts=new ArrayList<>();
//1.获取数据库的连接
Connection conn= JDBCUtils.getConnection();
//2.预编译sql语句,返回PreparedStatement的实例
PreparedStatement ps=conn.prepareStatement(sql);
//3.填充占位符
for (int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
//4.执行
ResultSet rs=ps.executeQuery();
//获取结果集元数据
ResultSetMetaData rsmd=rs.getMetaData();
//通过ResultSetMetaData获取结果集中的列数
int columncount=rsmd.getColumnCount();
while(rs.next()){
Account account=new Account();
//将数据库里每行对应的各列属性值赋给account对象的相应属性
for (int i=0;i<columncount;i++){
//获取该列的值
Object columnValue=rs.getObject(i+1);
//获取该列的名称
String columnName = rsmd.getColumnName(i + 1);
//获取该字段相关属性
Field field = account.getClass().getDeclaredField(columnName);
//提升权限
field.setAccessible(true);
//赋值
field.set(account,columnValue);
}//for
accounts.add(account);
}//while
JDBCUtils.close(conn,ps);
return accounts;
}
//登录实现
//Map类型参数是账户名和密码
public static boolean login(Map<String,String> userLoginInfo) throws ClassNotFoundException, SQLException, NoSuchFieldException, IllegalAccessException, IOException {
//定义sql
String sql="select * from account " +
"where useraccount = ? and userpassword = ?";
//获取所有匹配账号密码的account对象
List<Account> accounts = queryAccount(sql,userLoginInfo.get("account"),userLoginInfo.get("password"));
//如果该集合为0,代表账号或密码没有匹配,登录失败
//数据库中如果账号或密码没有匹配,那么返回null
if (accounts.size()==0){
return false;
}
return true;
}
}