zoukankan      html  css  js  c++  java
  • 【java】对数据库操作的那些事(包含数据库中的预处理)

    一、连接问题

    前面刚介绍了怎么连接数据库,也写了对应的模板。可是它的可维护性很差。那么怎么解决问题呢?

    首先写一个配置文件jdbc.properties

    <span style="font-size:18px;">## MySQL
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/hncu?

    useUnicode=true&characterEncoding=UTF-8 username=root password=1234 ## Oracle #driver=oracle.jdbc.driver.OracleDriver #url=jdbc:oracle:thin:@192.168.31.12:1521:orcl #username=scott #password=tiger </span>


    然后创建一个生成连接的工厂ConnFactory .java

    <span style="font-size:18px;">package cn.hncu.hibernate0;
    
    import java.io.IOException;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.util.Properties;
    
    public class ConnFactory {
    	private static Connection conn;
    	static {
    		try {
    			//读取配置文件
    			Properties p = new Properties();
    			p.load(ConnFactory.class.getClassLoader().getResourceAsStream("jdbc.properties"));
    			String driver = p.getProperty("driver");
    			String url = p.getProperty("url");
    			String username = p.getProperty("username");
    			String pwd = p.getProperty("password");
    			
    			Class.forName(driver);
    			conn = DriverManager.getConnection(url,username,pwd);
    			System.out.println("已连接到数据库..."+conn);
    		} catch (Exception e) {
    			throw new RuntimeException("读取配置文件失败", e);
    		}
    	}
    	public static Connection getConn(){
    		return conn;
    	}
    	public static void main(String[] args) {
    		getConn();
    	}
    }
    </span>
    最后直接通过ConnFactory.getConn()获得。

    这要做的优点,当改变所要连接的数据库类型时,仅仅须要改动配置文件里的内容就可以。


    二、解说getXXX()方法

    <span style="font-size:18px;"><span style="white-space:pre">	</span>@Test
    	public void getXXXDemo() throws Exception{
    		Statement st = ConnFactory.getConn().createStatement();
    		String sql = "select * from book";
    		ResultSet rs = st.executeQuery(sql);
    		while(rs.next()){
    			Integer id = rs.getInt(1);//这里的1表示数据表中的第一列,以下同理
    			String name = rs.getString(2);
    			//Double price = (Double)rs.getObject(3);//出异常,由于内部是採用BigDecimal来处理
    			Double price = rs.getDouble(3);
    			Object dateTime = rs.getObject(4);//把日期和时间作为一个总体读取出来
    			System.out.println(id+","+name+","+price+","+dateTime);
    			
    			String strDateTime = dateTime.toString();
    			System.out.println(strDateTime);
    			strDateTime = rs.getDate(4)+"--"+rs.getTime(4);//日期和时间能够单独获取
    			System.out.println(":::"+strDateTime);
    		}
    		ConnFactory.getConn().close();
    	}</span>
    注:对于自己主动增长列。删除之后再插入新记录,序号不会回头,继续往前增长。即中间会出现空号


    三、解说Statement中的三个executeXXX()方法

    1、executeQuery: 仅仅能运行select语句

    2、executeUpdate: 能够运行insert、delete和update语句,但不能运行select

    3、execute:增删改查的4种(随意)语句都能运行。该方法若运行非select语句时返回false,运行select语句时返回true,且st对象会缓存该次查询的结果。我

    们可通过ResultSet rs = st.getResultSet()来获得结果集

    <span style="font-size:18px;"><span style="white-space:pre">	</span>@Test
    	public void executeXXXDemo() throws Exception{
    		Statement st = ConnFactory.getConn().createStatement();
    	    String sql = "select * from book";
    		//String sql = "insert into book(name,price,pub) values('软件project',22.35,'2015-12-05 22:12:23')";
    		//String sql = "update book set price=38.88 where name='软件project'";
    		//String sql = "delete from book where name='软件project'";
    	    //st.executeQuery(sql);
    		//st.executeUpdate(sql);
    		boolean boo = st.execute(sql);
    		
    		if(boo){
    			ResultSet rs = st.getResultSet();
    			while(rs.next()){
    				System.out.println(rs.getObject(2));
    			}
    		}
    	}</span>


    四、数据库查询时防黑技术(预处理语句)

    案例、用户登录(通过用户输入信息来拼接sql语句----非常危急)

    <span style="font-size:18px;"><span style="white-space:pre">	</span>@Test//用户登录    
    	public void login() throws Exception{
    		Connection con = ConnFactory.getConn();
    		Statement st = con.createStatement();
    		Scanner sc = new Scanner(System.in);
    		int id = sc.nextInt(); sc.nextLine();
    		String name = sc.nextLine();
    		String sql = "select count(*) from stud where id="+id+" and sname='"+name+"'";
    		System.out.println("sql:"+sql);
    		ResultSet rs = st.executeQuery(sql);
    		rs.next();
    		int a = rs.getInt(1);
    		if(a<=0){
    			System.out.println("登录不成功");
    		}else{
    			System.out.println("登录成功");
    		}
    		
    		con.close();	   
    	}</span>
    黑的方法。输入:1002(回车)   1' or '1'='1
    因此:假设须要用 用户输入的信息 来拼接 sql语句,就不能用statement。否则用户能够通过构建where子句中的一个true条件来突破防护对于上面的情

    况,应该用PreparedStatement来解决!

    <span style="font-size:18px;"><span style="white-space:pre">	</span>@Test//用户登录     黑:1002(回车)   1' or '1'='1
    	public void login2() throws Exception{
    		Scanner sc = new Scanner(System.in);
    		
    		Connection con = ConnFactory.getConn();
    		String sql = "select count(*) from stud where id=? and sname=?";//须要用户输入的地方,用占位符('?')来取代。然后在兴许通过设參来给占位符赋值
    		PreparedStatement pst = con.prepareStatement(sql);
    		//设置參数
    		int id = sc.nextInt(); sc.nextLine();
    		pst.setInt(1, id); //參数1----代表第1个占位符
    		String name = sc.nextLine();
    		pst.setString(2, name);//參数2
    		
    		ResultSet rs = pst.executeQuery();
    		
    		rs.next();
    		int a = rs.getInt(1);
    		if(a<=0){
    			System.out.println("登录不成功");
    		}else{
    			System.out.println("登录成功");
    		}
    		
    		con.close();	   
    	}</span>


    五、获取自己主动增长列(如id)

    <span style="font-size:18px;"><span style="white-space:pre">	</span>@Test //演示获取自己主动增长列如id
    	public void saveAuto() throws Exception{
    		Connection con = ConnFactory.getConn();
    		String sql = "insert into book(name,price,pub) values('JavaEE',100.8,'2013-06-12 08:30:30')";
    		Statement st = con.createStatement();
    		
    		//st.executeUpdate(sql);
    		st.executeUpdate(sql,Statement.RETURN_GENERATED_KEYS);
    		ResultSet rs = st.getGeneratedKeys();//里面封装了自己主动生成的全部值
    		if(rs.next()){
    			int id = rs.getInt(1);//获取第1个自己主动增长列
    			System.out.println("自己主动增长的id:"+id);
    		}
    		System.out.println("-----------------");
    		
    		//预处理语句
    		sql =  "insert into book(name,price) values(?,?)";
    		PreparedStatement pst = con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
    		pst.setString(1, "计算机基础");
    		pst.setDouble(2, 28);
    		pst.executeUpdate();
    		ResultSet rs2 = pst.getGeneratedKeys();//里面封装了自己主动生成的全部值
    		if(rs2.next()){
    			int id = rs2.getInt(1);//获取第1个自己主动增长列
    			System.out.println("自己主动增长的id:"+id);
    		}
    	}</span>


    六、演示批处理语句

    public void batch() throws Exception{
    		Connection con = ConnFactory.getConn();
    		String sql = "insert into book(name,price,pub) values('JavaEE',100.8,'2015-06-12 08:30:30')";
    		Statement st = con.createStatement();
    		for(int i=0;i<10;i++){
    			st.addBatch(sql);
    		}
    		sql = "update book set price=price*1.1 where price>100";
    		st.addBatch(sql);
    		int[] a = st.executeBatch();
    		for(int r:a){
    			System.out.println(r);//r为每条sql语句所影响的记录数
    		}
    	}

    预处理

    public void preparedBatch() throws Exception{
    		Connection con = ConnFactory.getConn();
    		String sql = "insert into book(name,price,pub) values(?,?,?)";
    		PreparedStatement pst = con.prepareStatement(sql);
    		for(int i=0;i<5;i++){
    			pst.setString(1, "Java"+i);
    			pst.setDouble(2, 55.85+i);
    			pst.setString(3, "2016-12-10 07:07:08");
    			pst.addBatch(); //pst的方式不能带參数sql
    		}
    		//pst.executeBatch();
    		int[] a = pst.executeBatch();
    		for(int r:a){
    			System.out.println(r);//r为每条sql语句所影响的记录数
    		}
    	}

    注意:预处理的方式不能带參数sql,普通的须要



















  • 相关阅读:
    总结一些关于操作数据库是sql语句还是存储过程问题
    vs2010 创建预编译头 Debug 正常 Release Link Error问题解决
    创建Unicode格式的INI文件
    dos命令记录以及dos下通过进程id查找工作路径
    windows下多字节和宽字节转换
    关于多字节传输导致的乱码问题
    关于mysql数据库字符集优先级问题
    转: Apache开启gzip
    HTML 5 drag and drop 简介
    转: ES6异步编程: co函数库的含义与用法
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/7290907.html
Copyright © 2011-2022 走看看