文章目录
- 导入包
- con、stmt、rs 三者存在一定的关系
- getInt和getString
- input.nextInt();简单使用讲解
- ResultSet和Statement
- PreparedStatement的用法
- JDBC连接代码
- 更多样例
导入包
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.statement;
import java.sql.ResultSet;
import java.util.Scanner;import java sql.*;
con、stmt、rs 三者存在一定的关系
(1)连接数据库后 实例化con
(2)创建stmt=con.createstatement();
(3)然后执行rs=stmt.excuteQuery()执行sql语句,产生单个结果集;
getInt和getString
ResultSet rs = null;
String sql="SELECT flow_id,Type,id_card,exam_card,student_name,location,grade FROM examstudent";rs = st.executeQuery(sql); //rs:数据集
rs.getInt(int index);
rs.getInt(String columName); //你可以通过索引或者列名来获得查询结果集中的某一列的值。//举例
while(rs.next)
{rs.getInt(1)//等价于rs.getInt("flowid");rs.getString(5)//等价于rs.getInt("student_name");
}
input.nextInt();简单使用讲解
完整的写法是 先导入 输入流 类 Scanner
import java.util.Scanner;
然后使用输入流 , 按照你的问题中的 写法和名称, 应该这样使用 Scanner 这个类
Scanner input = new Scanner(System.in); // 创建输入流对象 input
int userNum = input.nextInt(); // 使用输入流对象 调用nextInt() 方法输入一个整数到userNum中
其意思是 使用 Scanner 类中的 nextInt() 方法 输入一个整数, 该方法只是接受一个 整型的数据,如果输入的是非整数数据, 将会 抛出 InputMismatchException
异常,其实就是专门为在命令式界面中 提供的一种输入类, Scanner 类位于 java.util 包中, 其中还有更多常用的其他方法。
例如:
nextLine() // 输入一行数据,一般会将你输入的数据当做 字符串处理
nextDouble() // 输入一个 双精度实型的 数据
nextFloat() // 输入一个 单精度实型的 数据
nextByte() // 输入一个字节的 数据
nextLong() // 输入一个long型的 数据,
等等, 如果输入错误的话, 或者输入的东西和你 调用的方法不匹配, 都会抛出 InputMismatchException
异常
ResultSet和Statement
ResultSet:
查询数据库时,返回的是一个二维的结果集,我们需要用到ResultSet来遍历结果集,获取每一行的数据。
boolean next() 将光标从当前位置向前移一行。
String getString(int columnIndex) 以java编程语言中String的形式获取此ResultSet对象的当前行中指定列的值
String getString(String columnLabel) 以java编程语言中String的形式获取此ResultSet对象的当前行中指定列的值
while(rs.next()) {int id = rs.getInt(1);// 获取第一个列的值 编号idString bookName = rs.getString(2);// 获取第二个列的值 图书名称 bookNameString author = rs.getString(3);// 获取第三列的值 图书作者 authorfloat price = rs.getFloat(4);// 获取第四列的值 图书价格 priceSystem.out.println("id="+id+" bookName="+bookName+" author="+author+" price="+price);System.out.println("................................................");
Statement :
(1)建立了到特定数据库的连接之后,就可用该连接发送 SQL 语句。
(2)Statement 接口提供了三种执行 SQL 语句的方法:executeQuery、executeUpdate 和execute
1.方法 executeQuery 用于产生单个结果集的语句,例如 SELECT 语句
2.方法 executeUpdate 用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQLDDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。 INSERT、UPDATE 或
DELETE语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个整数,指示受影响的行数(即更新计数)。
对于CREATE TABLE 或 DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。
3.方法 execute用于执行返回多个结果集、多个更新计数或二者组合的语句。
PreparedStatement的用法
java.sql.statement要求开发者付出大量的时间和精力。
在使用statement获取jdbc访问时所具有的一个共通的问题是输入适当格式的日期和时间戳:2002-02-05 20:56 或者 02/05/02 8:56 pm。
通过使用java.sql.preparedstatement,可以自动解决这个问题。
一个preparedstatement是从java.sql.connection对象和所提供的sql字符串得到的,sql字符串中包含问号(?),这些问号标明变量的位置,然后提供变量的值,最后执行语句,例如:
string sql = "select * from people p where p.id = ? and p.name = ?";
preparedstatement ps = connection.preparestatement(sql);
ps.setint(1,id);
ps.setstring(2,name);
resultset rs = ps.executequery();
使用preparedstatement的另一个优点是字符串不是动态创建的。
下面是一个动态创建字符串的例子:
string sql = "select * from people p where p.i = "+id;
这允许jvm(java virtual machine)和驱动/数据库缓存语句和字符串并提高性能。
preparedstatement也提供数据库无关性。当显示声明的sql越少,那么潜在的sql语句的数据库依赖性就越小。
由于preparedstatement具备很多优点,开发者可能通常都使用它,只有在完全是因为性能原因或者是在一行sql语句中没有变量的时候才使用通常的statement。
import java.sql.*;
public class mypreparedstatement {private final string db_driver="com.microsoft.jdbc.sqlserver.sqlserverdriver";private final string url = "jdbc:microsoft:sqlserver://127.0.0.1:1433;databasename=pubs";public mypreparedstatement() {}public void query() throws sqlexception {connection conn = this.getconnection();string strsql = "select emp_id from employee where emp_id = ?";preparedstatement pstmt = conn.preparestatement(strsql);pstmt.setstring(1,"pma42628m");resultset rs = pstmt.executequery();while(rs.next()) {string fname = rs.getstring("emp_id");system.out.println("the fname is " + fname);}rs.close();pstmt.close();conn.close();}private connection getconnection() throws sqlexception {
// class.connection conn = null;try {class.forname(db_driver);conn = drivermanager.getconnection(url,"sa","sa");} catch (classnotfoundexception ex) {}return conn;}
//mainpublic static void main(string[] args) throws sqlexception {mypreparedstatement jdbctest1 = new mypreparedstatement();jdbctest1.query();}
}
为什么要始终使用PreparedStatement代替Statement?为什么要始终使用PreparedStatement代替Statement?
在JDBC应用中,应该始终以PreparedStatement代替Statement.也就是说,在任何时候都不要使用Statement。
基于以下的原因:
一.、代码的可读性和可维护性.
虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.都比直接用Statement的代码高很多档次:
stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate();
对于第一种方法.别说其他人去读你的代码,就是你自己过一段时间再去读,都会觉得伤心。
二、PreparedStatement尽最大可能提高性能
每一种数据库都会尽最大努力对预编译语句提供最大的性能优化.因为预编译语句有可能被重复调用.
所以语句在被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)就会得到执行.这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行。
而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.比如:
insert into tb_name (col1,col2) values (‘11’,‘22’);
insert into tb_name (col1,col2) values (‘11’,‘23’);
即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义。事实是没有数据库会对普通语句编译后的执行代码缓存.
当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果,以保存有更多的空间存储新的预编译语句。
三、最重要的一点是极大地提高了安全性.
常见的SQL注入:
String sql = "select * from tb_name where name= '"+varname+"' and passwd='"+varpasswd+"'";
如果我们把[’ or ‘1’ = '1]作为passwd变量传入进来。
select * from tb_name = '随意' and passwd = '' or '1' = '1';
因为’1’='1’肯定成立,所以可以任何通过验证.
更有甚者:
把[';drop table tb_name;]
作为varpasswd传入进来,有
select * from tb_name = '随意' and passwd = '';drop table tb_name;
有些数据库是不会让你成功。.
而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.只要全使用预编译语句,你就用不着对传入的数据做任何过虑.而如果使用普通的statement,有可能要对drop,;等做费尽心机的判断和过虑。
JDBC连接代码
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;public class JDBCUtil {static String driverClass=null;static String url=null;static String name=null;static String password=null;static {try{//1.创建一个属性对象Properties properties=new Properties();InputStream is=JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");//导入输入流properties.load(is);//读取属性driverClass= properties.getProperty("driverClass");url= properties.getProperty("url");name= properties.getProperty("name");password= properties.getProperty("password");} catch(Exception e) {e.printStackTrace();}}public static Connection getConn() {Connection conn=null;try {Class.forName(driverClass);//1.注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver());// 2.建立连接 参数一:协议+访问的数据库 参数二: 用户名 参数三:密码//conn=DriverManager.getConnection("jdbc:mysql://localhost/test?useSSL=false","root","1234");conn=DriverManager.getConnection(url,name,password);} catch(Exception e) {e.printStackTrace();}return conn;}
// 释放资源public static void release(Connection conn,Statement st,ResultSet rs) {closeRs(rs);closeSt(st);closeConn(conn);}private static void closeRs(ResultSet rs) {try {if(rs!=null) {rs.close();}} catch (SQLException e) {e.printStackTrace();}finally {rs=null;}}private static void closeSt(Statement st) {try {if(st!=null) {st.close();}} catch (SQLException e) {e.printStackTrace();}finally {st=null;}}private static void closeConn(Connection conn) {try {if(conn!=null) {conn.close();}} catch (SQLException e) {e.printStackTrace();}finally {conn=null;}}}
更多样例
class DBConnection{// 驱动类名String driver="com.mysql.jdbc.Driver";
// URL格式,最后为数据库名String url="jdbc:mysql://localhost:3306/javaTest?useUnicode=true&characterEncoding=UTF8"; //JavaTest为你的数据库名称String user="root";String password="123456";Connection coon=null;public DBConnection(){try{
// 加载驱动程序Class.forName(driver);coon=(Connection)DriverManager.getConnection(url,user,password);if(!coon.isClosed()){System.out.println("成功连接数据库!");}}catch (Exception e){e.printStackTrace();}}public void close(){try{this.coon.close();}catch(Exception e){e.printStackTrace();}}
// 增加数据public void add(String name,int age,String gender){
// String sql="insert into usrInfo(username,gender,age) values(?,?,?)"; //向usrInfo表中插入数据String sql="insert into usrInfo(age,gender,username) values('"+age+"','"+gender+"','"+name+"')";try{PreparedStatement preStmt=(PreparedStatement)this.coon.prepareStatement(sql);
// preStmt.setString(1, name);
// preStmt.setInt(3, age);
// preStmt.setString(2, gender); //和上面的注释的一块组成另外一种插入方法preStmt.executeUpdate();System.out.println("插入数据成功!");preStmt.close();}catch(Exception e){e.printStackTrace();}}// 查询public void select(){String sql="select * from usrInfo"; //查询usrInfo表中的信息try{Statement stmt=(Statement)this.coon.createStatement();ResultSet rs=(ResultSet)stmt.executeQuery(sql); //得到的是结果的集合System.out.println("--------------------------------");System.out.println("姓名"+"\t"+"年龄"+"\t"+"性别");System.out.println("--------------------------------");while(rs.next()){String name=rs.getString("username");int age=rs.getInt("age");String gender=rs.getString("gender");System.out.println(name+"\t"+age+"\t"+gender);}stmt.close();}catch(Exception e){e.printStackTrace();}}// 更改数据public void update(String name,int age){String sql="update usrInfo set age=? where username=?"; //推荐使用这种方式,下面的那种注释方式不知道为啥有时候不好使
// String sql="update usrInfo set age="+age+" where username='"+name+"'";try{PreparedStatement prestmt=(PreparedStatement)this.coon.prepareStatement(sql);prestmt.setInt(1, age);prestmt.setString(2,name);prestmt.executeUpdate();// Statement stmt=(Statement)this.coon.createStatement();
// stmt.executeUpdate(sql);System.out.println("更改数据成功!");prestmt.close();}catch(Exception e){e.printStackTrace();}}// 删除数据public void del(String name){String sql="delete from usrInfo where username=?";try{PreparedStatement prestmt=(PreparedStatement)this.coon.prepareStatement(sql);prestmt.setString(1, name);prestmt.executeUpdate();System.out.println("删除数据成功!");prestmt.close();}catch(Exception e){e.printStackTrace();}}
}
在主类中对其创建实例,实例中构造方法完成数据库的连接操作,实例调用增删改查方法进行对数据库信息的操作
public class mysqlTest {public static void main(String args[]){Scanner in=new Scanner(System.in);DBConnection db=new DBConnection();// 插入数据System.out.println("输入姓名,年龄,性别:");String name=in.next();int age=in.nextInt();String gender=in.next();db.add(name, age, gender);// 查询数据db.select();// 修改数据
// String name=in.next();
// int age=in.nextInt();
// db.update(name, age);// 删除数据
// String name=in.next();
// db.del(name);
//
// db.close();}}