JDBC

JDBC

1,JDBC概述

JDBC(Java DataBase Connectivity) java数据库连接。是一套通过java操作数据的公共规范。
作用:JAVA程序连接访问关系型数据库的。

2, JDBC快速入门

2.1 实现步骤

  1. 导入数据库jdbc驱动包
  2. 配置数据库连接相关信息
  3. 通过Class.forName、DriverManager加载驱动并创建Connection对象连接数据库
  4. 通过Connection对象创建PrepareStatement对象发送sql到数据库并执行
  5. 通过PrepareStatement设置参数(如果sql没有占位符则跳过)
  6. 执行sql,获取结果
  7. 关闭连接

**DQL: **

public class JDBCTest {

    public static void main(String[] args) throws Exception {
        //配置数据库连接信息
        //数据库驱动
        String driverClass = "com.mysql.jdbc.Driver";
        //数据库url
        String url = "jdbc:mysql://localhost:3306/eshop?useUnicode=true&characterEncoding=UTF-8";
        //用户名
        String user = "root";
        //密码
        String password = "123456";

        //加载数据库驱动
        Class.forName(driverClass);
        //创建数据库连接
        Connection conn = DriverManager.getConnection(url, user, password);
        //发送sql语句到数据库
        PreparedStatement pst = conn.prepareStatement(
        "select * from student");
        //执行sql语句并返回结果
        ResultSet rs = pst.executeQuery();
        //提取执行结果
        while(rs.next()) {
            System.out.println("name: " + rs.getString("stu_name") + " password: " + rs.getString(2));
        }
        conn.close();
    }
}

**DML: **

public class JDBCTest {

    public static void main(String[] args) throws Exception {
        //配置数据库连接信息
        //数据库驱动
        String driverClass = "com.mysql.jdbc.Driver";
        //数据库url
        String url = "jdbc:mysql://localhost:3306/eshop?useUnicode=true&characterEncoding=UTF-8";
        //用户名
        String user = "root";
        //密码
        String password = "123456";

        //加载数据库驱动
        Class.forName(driverClass);
        //创建数据库连接
        Connection conn = DriverManager.getConnection(url, user, password);
        //发送sql语句到数据库
        PreparedStatement pst = conn.prepareStatement(
        "delete from student where stu_id = ? ");
        //执行sql语句并返回结果
        int i = pst.executeUpdate();
        //提取执行结果
        if(i>0){
			System.out.println("删除成功");
		}else{
			System.out.println("删除失败");
    	}
        conn.close();
    }
}

2.2 代码实现说明

Connection接口:与特定数据库的连接(会话)。
PreparedStatement接口:表示预编译的 SQL 语句的对象。SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。

ResultSet接口:表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。ResultSet 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next 方法将光标移动到下一行;因为该方法在 ResultSet 对象没有下一行时返回 false,所以可以在 while 循环中使用它来迭代结果集。

2.3 SQL注入

在定义SQL的时候把用户输入的内容作为参数跟SQL拼接的话,当用户输入不合理的数据值的时候有可能导致SQL执行异常。
例如:
正常的登录SQL : select * from student where stu_name = ‘seven’ and stu_pwd = ‘123’ 其中seven123为用户从界面传入的登录账号,如果用户输入字段带’号则会异常。

如果用户输入 1’ or 1='1 时候则拼接的SQL为 select * from student where stu_name = ‘1’ or 1=‘1’ and stu_pwd = ‘123’
此时用户只知道用户名不知道密码则也可以登录成功。

再例如如果用户输入 abc’ or 1=‘1’ – (最后要有个空格)则拼接的SQL为
select * from student where stu_name = ‘abc’ or 1=‘1’ – ’ and stu_pwd = ‘123’
则用户此时不知道用户名跟密码情况都可以登录成功。

2.4 JDBC事务管理

事务是数据库中非常重要的一个特性,事务属于原子性操作,是数据库执行过程中的一个逻辑单位,要么全部成功要么全部失败。

Connection接口中的事务操作

  • pulic void commit() 事务提交
  • pulic void rollback() 事务回滚
  • pulic void setAutoCommit(boolean autoCommit) 执行是否自动提交事务,默认自动提交事务
public class JDBCTest {

    public static void main(String[] args) throws SQLException {
        //配置数据库连接信息
        //数据库驱动
        String driverClass = "com.mysql.jdbc.Driver";
        //数据库url
       String url = "jdbc:mysql://localhost:3306/eshop?useUnicode=true&characterEncoding=UTF-8";
        //用户名
        String user = "root";
        //密码
        String password = "123456";

        Connection conn = null;

        try {
            //加载数据库驱动
            Class.forName(driverClass);
            //创建数据库连接
            conn = DriverManager.getConnection(url, user, password);
            //设置事务为手动提交
            conn.setAutoCommit(false);
            //发送sql语句到数据库
            // 添加一条数据
            PreparedStatement pst1 = conn.prepareStatement("insert into student(stu_name, stu_password, stu_age) values(?,?,?)");
            pst.setString(1, "seven");
            pst.setString(2, "123");
            pst.setInt(2, 20);
            //执行sql语句并返回结果
            int count1 = pst.executeUpdate();
            // 删除一条数据
             PreparedStatement pst2 = conn.prepareStatement("delete from student where stu_name = ? ");
            pst.setString(1, "zhangsan");            
            //执行sql语句并返回结果
            int count2 = pst.executeUpdate();
            
            //事务提交:事务内的添加操作跟删除操作要么全部成功,要么全部失败。
            conn.commit();
            //受影响条数
            System.out.println("count: " + count);
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
            conn.rollback();
        }

    }
}

3 其它

3.1 Statement与PreparedStatement的区别

  1. PreparedStatement是预编译的,对于多次执行的SQL可以大大提高效率。而Statement不行

  2. PreparedStatement可以通过占位符的方式解决SQL注入的问题,而Statement不行

  3. 2者SQL的传入位置不同

//	Statement code :
   Statement statement = conn.createStatement();
   String sqlString = " delete from student where stu_name ='seven' " ;
   statement.executeUpdate(sqlString);
//PreparedStatement code:
   PreparedStatement updateSales = conn.prepareStatement("delete from student where stu_name ='seven' "); 
updateSales.executeUpdate();

3.2 使用Batch功能

当执行一行的SQL,不同的参数值(比如插入N条数据)的时候可以使用PreparedStatement的Batch功能。这样不管操作多少条数据都只需要2次网络往返(1次是预存储statement,1次是执行batch命令)。

​ 注意:

  • 事务的设置,不能使自动提交,要批量添加后才提交。

  • 在mysql 下使用批量执行的时候要在url 后面添加rewriteBatchedStatements=true,不添加的话可以运行但没有批量操作的效率提升。

    String url=“jdbc:mysql://localhost:3306/XXdb?rewriteBatchedStatements=true”

	// statement executeBatch  code :
	con.setAutoCommit(false);	
	Statement stmt = conn.createStatement();
	stmt.addBatch("INSERT into student values ('张三','123','18'))");
	stmt.addBatch("INSERT into student values ('李四','456','21'))");
	stmt.addBatch("INSERT into student values ('王五','789','22'))");
	
	int [] updateCounts=stmt.executeBatch();
	con.commit();
	stmt.clearBatch();


//	PreparedStatement executeBatch  code :
conn.setAutoCommit(false);
PreparedStatement ps = conn.prepareStatement("insert into student values (?,?,?))";
	for (n = 0; n < 100; n++) {
	ps.setString(1,n+"");
	ps.setLong(2,n+"");
	ps.setInt(3,n+"");
    ps.addBatch();
}
int [] = ps.executeBatch();
con.commit();
ps.clearBatch();

4 dbutils

dbutils是Apache公司开发的一个封装了JDBC的框架。是一种用于执行SQL语句的JAVA API,可以为多种关系数据库提供统一访问。
下载地址 http://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi

4.1 dbutils的使用

新增(删除、修改类似)

// 先获取连接
Connection conn = DBHelper.getConn();
// 创建QueryRunner对象
QueryRunner qr = new QueryRunner();
// 定义SQL
String sql = "insert into  student(stu_name,stu_pwd) values(?,?)" ;
// 执行SQL,获取结果
int i = qr.update(conn, sql,"古天乐","123");

查询

// 先获取连接
Connection conn = DBHelper.getConn();
// 创建QueryRunner对象
QueryRunner qr = new QueryRunner();
// 定义SQL
String sql = "select * from student " ;
// 执行查询,BeanListHandler表示把结果封装到一个Student对象的List集合中
// Bean中的属性必须跟数据库中的字段名一样才可以映射上
List<Student> list =  qr.query(conn, sql,new BeanListHandler<Student>(Student.class));
DBHelper.closeConn(conn);

重点在BeanListHandler,它是ResultSetHandler<T>接口的实现类,每种实现类表示将结果封装成不同的对象。

  • 1 BeanListHandler将查询结果的每一行封装到Bean对象,然后再存入List集合
String sql = "select * from student " ;
List<Student> list =  qr.query(conn, sql,new BeanListHandler<Student>(Student.class));
  • 2 BeanHandler将查询结果的第一行数据,封装到Bean对象
String sql = "select * from student where stu_id = ? and stu_name =? " ;
Student bean =  qr.query(conn, sql,new BeanHandler<Student>(Student.class),101,"zhangsan");
    说明:如果SQL中有参数的占位符则在后面添加占位符对应的参数,个数、类型跟SQL中的?号要对应。
    也可以把所有参数值封装到数组中一次性传入,如:Object param = {101,"zhangsan"};然后将param在后面传入。

  • 3 ColumnListHandler 将查询结果的指定列的数据封装到List集合中
String sql = "select stu_name from student " ;
List<Object> list =  (List<Object>) qr.query(conn, sql,new ColumnListHandler());
  • 4 ScalarHandler 封装结果为单行单列的结果,类似count、avg、max、min、sum…函数
String sql = "select count(*) from student " ;
Object object =  qr.query(conn, sql,new ScalarHandler<Object>()); 
  • 5 ArrayHandler:将查询结果的第一行数据,保存到Object数组中
String sql = "select * from student " ;
Object [] object =  qr.query(conn, sql,new ArrayHandler()); 
  • 6 ArrayListHandler 将查询的结果,每一行先封装到Object数组中,然后将数据存入List集合
String sql = "select * from student " ;
List<Object []> list =  qr.query(conn, sql,new ArrayListHandler()); 
  • 7 MapHandler 将查询结果的第一行数据封装到map结合(key=列名,value=列值)
String sql = "select * from student " ;
Map<String,Object> map =  qr.query(conn, sql,new MapHandler()); 
  • 8 MapListHandler将查询结果的每一行封装到map集合(key=列名,value=列值),再将map集合存入List集合
String sql = "select * from student " ;
List<Map<String,Object>> list =  qr.query(conn, sql,new MapListHandler()); 

**在上述封装中需要Bean中的属性必须跟数据库中的字段名一样才可以映射上。但是数据库字段一般带下划线,如stu_name,而java中属性一般使用小驼峰命名,2者不一致。则需要在定义Handler的时候传入一个BasicRowProcessor对象。DButils已经默认创建了GenerousBeanProcessor可以直接下划线字段到小驼峰的转换。如: **

String sql = " select * from student";
BasicRowProcessor brp = new BasicRowProcessor(new GenerousBeanProcessor());
List<Student> list = runner.query(conn,sql, new BeanListHandler<Student>(Student.class,brp));

如果数据库字段跟bean中的属性命名不仅仅是下划线的区别的话,则需要使用其它的Processor,如:

// 要先把数据库字段跟属性字段全部映射关系存入到Map,在定义到BeanProcessor中
	Map<String,String> map = new HashMap<>(); 
	map.put("stu_id","stuId");
	map.put("stu number","stuNumber");//数据库中字段是空格,属性是小驼峰
	map.put("stu_name","stuName");
	map.put("stu_age","stuAge");
	map.put("stu_sex","stuSex");
	map.put("stu_brithday","stuBrithday");		

	BasicRowProcessor brp = new BasicRowProcessor(new BeanProcessor(map));
	List<Student1> list = runner.query(conn,sql, new BeanListHandler<Student>(Student.class,brp));

5 连接池

5.1 获取DataSource对象

  • 1 方式1
    DruidDataSource ds = new DruidDataSource();
    ds.setUrl(URL);
    ds.setUsername(USER);
    ds.setPassword(PWD);
    ds.setDriverClassName(DRIVER);
  • 2 方式2
    Map<String,String> map = new HashMap<String,String>();
    map.put("driverClassName", DRIVER);
    map.put("url", URL);
    map.put("username", USER);
    map.put("password", PWD);

    DataSource ds = DruidDataSourceFactory.createDataSource(map);
  • 3 方式3
	driverClassName=com.mysql.jdbc.Driver
	url=jdbc:mysql://127.0.0.1:3306/test1?useUnicode=true&characterEncoding=UTF-8
	username=root
    password=root
   Properties p = new Properties();
   InputStream is = new FileInputStream(new File("src/datasource.properties"));
   p.load(is);
   DataSource ds = DruidDataSourceFactory.createDataSource(p);

5.2 使用DataSource对象

	QueryRunner qr = new QueryRunner(ds);
	String sql = " select * from student " ;
	List<Student> list = qr.query(sql, new BeanListHandler<Student>(Student.class));
	QueryRunner qr = new QueryRunner( );
	String sql = " select * from student " ;
	List<Student> list = qr.query(ds.getConnection(),sql, new  	  BeanListHandler<Student>(Student.class));

如果不需要DataSource对象,而需要原始的Connection对象的话也可以通过DataSource的getConnection()方法获取连接对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值