Java连接Mysql数据库(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);// 获取第一个列的值 编号id

	String bookName = rs.getString(2);// 获取第二个列的值 图书名称 bookName

	String author = rs.getString(3);// 获取第三列的值 图书作者 author

	float price = rs.getFloat(4);// 获取第四列的值 图书价格 price

	System.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;
		}
//main
		public 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();
    }

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值