JDBC
加载驱动 反射 Class.forName(“com.mysql.jdbc.Driver”);
获取到连接 Connection connection = DriverManager.getConnection(url,user,pwd);
comboPooledDataSource.getConnection()
创建预处理对象 connection.preparedStatement(sql)
执行sql语句 PreparedStatement executeUpdate() executeQuery() execute() setxxx(索引(->1),值); setObject(索引,值);
结果集 链表
while (resultSet.next()) { //Object object = resultSet.getObject(1);取对象 int id = resultSet.getInt(1); //int id1 = resultSet.getInt("id"); 列名 String name = resultSet.getString(2); String sex = resultSet.getString(3); Date date = resultSet.getDate(4); System.out.println(id + "\t" + name + "\t" + sex + "\t" + date); }
概念:
JDBC (Java DB Connection)---Java数据库连接
JDBC是一种可用于执行SQL语句的JAVA API(ApplicationProgramming Interface应用程序设计接口)。它由一些Java语言编写的类和界面组成。
JDBC为数据库应用开发人员和数据库前台工具开发人员提供了一种标准的应用程序设计接口,使开发人员可以用纯JAVA语言编写完整的数据库应用程序。
JDBC代表JAVA数据库连接。它是一个软件层,允许开发者在JAVA中编写客户端/服务器应用。
一、ODBC到JDBC的发展历程
ODBC是OpenDatabaseConnectivity的英文简写。它是一种用来在相关或不相关的数据库管理系统(DBMS)中存取数据的,用C语言实现的,标准应用程序数据接口。通过ODBCAPI,应用程序可以存取保存在多种不同数据库管理系统(DBMS)中的数据,而不论每个DBMS使用了何种数据存储格式和编程接口。
1.ODBC的结构模型
ODBC的结构包括四个主要部分:应用程序接口、驱动器管理器、数据库驱动器和数据源。
应用程序接口:屏蔽不同的ODBC数据库驱动器之间函数调用的差别,为用户提供统一的SQL编程接口。
驱动器管理器:为应用程序装载数据库驱动器。
数据库驱动器:实现ODBC的函数调用,提供对特定数据源的SQL请求。如果需要,数据库驱动器将修改应用程序的请求,使得请求符合相关的DBMS所支持的文法。
数据源:由用户想要存取的数据以及与它相关的操作系统、DBMS和用于访问DBMS的网络平台组成。
虽然ODBC驱动器管理器的主要目的是加载数据库驱动器,以便ODBC函数调用,但是数据库驱动器本身也执行ODBC函数调用,并与数据库相互配合。因此当应用系统发出调用与数据源进行连接时,数据库驱动器能管理通信协议。当建立起与数据源的连接时,数据库驱动器便能处理应用系统向DBMS发出的请求,对分析或发自数据源的设计进行必要的翻译,并将结果返回给应用系统。
2.JDBC的诞生
自从Java语言于1995年5月正式公布以来,Java风靡全球。出现大量的用java语言编写的程序,其中也包括数据库应用程序。由于没有一个Java语言的API,编程人员不得不在Java程序中加入C语言的ODBC函数调用。这就使很多Java的优秀特性无法充分发挥,比如平台无关性、面向对象特性等。随着越来越多的编程人员对Java语言的日益喜爱,越来越多的公司在Java程序开发上投入的精力日益增加,对java语言接口的访问数据库的API的要求越来越强烈。也由于ODBC的有其不足之处,比如它并不容易使用,没有面向对象的特性等等,SUN公司决定开发一Java语言为接口的数据库应用程序开发接口。在JDK1.x版本中,JDBC只是一个可选部件,到了JDK1.1公布时,SQL类包(也就是JDBCAPI)就成为Java语言的标准部件。
二、JDBC技术概述
JDBC是一种可用于执行SQL语句的JavaAPI(ApplicationProgrammingInterface,应用程序设计接口)。
通过使用JDBC,开发人员可以很方便地将SQL语句传送给几乎任何一种数据库。也就是说,开发人员可以不必写一个程序访问Sybase,写另一个程序访问Oracle,再写一个程序访问Microsoft的SQLServer。用JDBC写的程序能够自动地将SQL语句传送给相应的数据库管理系统(DBMS)。不但如此,使用Java编写的应用程序可以在任何支持Java的平台上运行,不必在不同的平台上编写不同的应用。Java和JDBC的结合可以让开发人员在开发数据库应用时真正实现“WriteOnce,RunEverywhere!”
Java具有健壮、安全、易用等特性,而且支持自动网上下载,本质上是一种很好的数据库应用的编程语言。它所需要的是Java应用如何同各种各样的数据库连接,JDBC正是实现这种连接的关键。
JDBC扩展了Java的能力,如使用Java和JDBCAPI就可以公布一个Web页,页中带有能访问远端数据库的Ap plet。或者企业可以通过JDBC让全部的职工(他们可以使用不同的操作系统,如Windwos,Machintosh和UNIX)在In tranet上连接到几个全球数据库上,而这几个全球数据库可以是不相同的。随着越来越多的程序开发人员使用Java语言,对Java访问数据库易操作性的需求越来越强烈。
JDBC API定义了一组用于与数据库通信的接口和类。这些接口和类位于java.sql包中。
JDBC是用来(让我们的程序)通过网络来操作数据库的,作用很重要;JDBC技术也是Java核心技术之一。凡是需要用网络操作数据库的程序,JDBC编程有问题,一切都是白搭。
三、JDBC技术及使用详解
从结构图中可以看出,通过JDBC API 让我们的Java应用程序可以利用JDBCDriver Manager[JDBC驱动管理],连接到JDBC驱动;体现在我们的工程中也就是要导入驱动jar包。
何谓驱动?
不同的数据库厂商或者同一厂商的不同数据库版本都会提供不同的驱动,任何应用程序都是通过这个驱动来操作特定厂商、特定版本的数据库的。
使用JDBC的第一步就是要注册(加载)这个驱动。 JDBC驱动程序的分类
第一类JDBC驱动程序是JDBC-ODBC桥再加上一个ODBC驱动程序。
这类驱动一般不用现在的编程应用中。
第二类JDBC驱动程序是部分JAVAAPI代码的驱动程序,用于把JDBC调用转换成主流数据库API的本机调用。
第三类JDBC驱动程序是面向数据库中间件的纯JAVA驱动程序,JDBC调用被转换成一种中间件厂商的协议,中间件再把这些调用转换到数据库API。
第四类JDBC驱动程序是直接面向数据库的纯JAVA驱动程序。
是使用JDBC驱动程序访问数据库的首选方式
通过JDBC操作数据库——步骤:
第1步:注册驱动 (只做一次)
第2步:建立连接(Connection)
第3步:创建执行SQL的语句(Statement)
第4步:执行语句
第5步:处理执行结果(ResultSet)
第6步:释放资源
使用JDBC第一步:加载驱动
注册驱动有三种方式:
通过Properties对象获取配置文件的信息 Properties properties = new Properties(); properties.load(new FileInputStream("src\\com\\hl25\\hspedu\\mysql.properties")); //获取相关的值 String user = properties.getProperty("user"); String password = properties.getProperty("password"); String driver = properties.getProperty("driver"); String url = properties.getProperty("url");
1.:加载驱动
注册驱动有三种方式:
Class.forName(“com.mysql.jdbc.Driver”);
推荐这种方式,不会对具体的驱动类产生依赖
//1. 注册驱动 Class.forName(driver);//建议写上DriverManager.registerDriver(com.mysql.jdbc.Driver);
会对具体的驱动类产生依赖
System.setProperty(“jdbc.drivers”, “driver1:driver2”);
虽然不会对具体的驱动类产生依赖;但注册不太方便,所以很少使用
2.:建立连接(连接池)
通过Connection建立连接,Connection是一个接口类,其功能是与数据库进行连接(会话)。
建立Connection接口类对象:
Connection conn =DriverManager.getConnection(url, user, password);
其中URL的格式要求为:
JDBC:子协议:子名称//主机名:端口/数据库名?属性名=属性值&…
如:"jdbc:mysql://localhost:3306/test“
user即为登录数据库的用户名,如root
password即为登录数据库的密码,为空就填””
//2. 得到连接 Connection connection = DriverManager.getConnection(url, user, password);c3p0:
//1. 将c3p0 提供的 c3p0.config.xml 拷贝到 src目录下 //2. 该文件指定了连接数据库和连接池的相关参数 ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("admin"); Connection connection = comboPooledDataSource.getConnection(); //这个方法就是从 DataSource 接口实现的 connection.close();druid:
Properties properties = new Properties(); properties.load(new FileInputStream("src\\druid.properties")); //4. 创建一个指定参数的数据库连接池, Druid连接池 DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); Connection connection = dataSource.getConnection();:
3.:创建执行对象
执行对象Statement负责执行SQL语句,由Connection对象产生。
Statement接口类还派生出两个接口类PreparedStatement和CallableStatement,这两个接口类对象为我们提供了更加强大的数据访问功能。
创建Statement的语法为:
//3. 得到Statement(不用) Statement statement = connection.createStatement();//3. 得到PreparedStatement PreparedStatement pstmt = connection.prepareStatement(sql);//得到QueryRunner QueryRunner queryRunner = new QueryRunner();
4.:执行SQL语句(批处理)
执行对象Statement提供两个常用的方法来执行SQL语句。
executeQuery(Stringsql),该方法用于执行实现查询功能的sql语句,返回类型为ResultSet(结果集)。
如:ResultSet rs =st.executeQuery(sql);
executeUpdate(Stringsql),该方法用于执行实现增、删、改功能的sql语句,返回类型为int,即受影响的行数。
如:int flag = st.executeUpdate(sql);
execute(),该方法用于执行任意sql语句,返回类型为Boolean
如:boolean flag = st.execute(sql);
setxxx(),占位符索引,解决SQL注入问题
如:st.setString(索引,值);
//4. 组织SqL(不用) String sql = "select id, name , sex, borndate from actor"; ResultSet resultSet = statement.executeQuery(sql);//4. 组织SqL String sql = "insert into t_course(course_name) values(?)"; PreparedStatement pstmt = connection.prepareStatement(sql); pstmt.setString(1, courseName); //给占位符赋值 ResultSet resultSet =pstmt.executeUpdate(); //执行Apache-DBUtils: List<Actor> list = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1);//多行 //Actor actor = queryRunner.query(connection, sql, new BeanHandler<>(Actor.class), 10);//单行 //Object obj = queryRunner.query(connection, sql, new ScalarHandler(), 4);//单反单列 //int affectedRow = queryRunner.update(connection, sql, "林青霞", 1);//改 //int affectedRow = queryRunner.update(connection, sql, "林青霞", "女", "1966-10-10", "116");//增 //int affectedRow = queryRunner.update(connection, sql, 1000 );//删批量执行SQL语句:
url添加参数 ?rewriteBatchedStatements=true for(int i;i<1000;i++){ pstmt.setString(1, courseName); //给占位符赋值 pstmt.addBatch()//添加到批处理包 if(i%1000==0){ pstmt.executeBatch()//批量处理 pstmt.clearBatch()//清空处理包 } }
5.:处理执行结果
ResultSet对象(结果集)
ResultSet对象负责保存Statement执行后所产生的查询结果。
结果集ResultSet是通过游标来操作的。
游标就是一个可控制的、可以指向任意一条记录的指针。有了这个指针我们就能轻易地指出我们要对结果集中的哪一条记录进行修改、删除,或者要在哪一条记录之前插入数据。一个结果集对象中只包含一个游标。
//5. 使用while取出数据 while (resultSet.next()) { // 让光标向后移动,如果没有更多行,则返回false //Object object = resultSet.getObject(1);取对象 int id = resultSet.getInt(1); //获取该行的第1列 **********//int id1 = resultSet.getInt("id"); 通过列名来获取值, 推荐 String name = resultSet.getString(2);//获取该行的第2列 String sex = resultSet.getString(3); Date date = resultSet.getDate(4); System.out.println(id + "\t" + name + "\t" + sex + "\t" + date); }
6.——释放资源
Connection对象的close方法用于关闭连接,并释放和连接相关的资源。
//6. 关闭连接 resultSet.close(); statement.close(); connection.close();
接口
PreperedStatement接口
PreperedStatement从Statement扩展而来。
需要多次执行SQL语句,可以使用PreparedStatement。
PreparedStatement可以对SQL语句进行预编译
并且可以存储在PreparedStatement对象中,当多次执行SQL语句时可以提高效率。
作为Statement的子类,PreparedStatement继承了Statement的所有函数。
创建PreperedStatement
PreparedStatementstr=conn.prepareStatement(sql);//此处?为通配符
其他的CRUD方法和Statement基本一致。
CallableStatement接口
CallableStatement类继承了PreparedStatement类,他主要用于执行SQL存储过程。
在JDBC中执行SQL存储过程需要转义。
JDBC API提供了一个SQL存储过程的转义语法:
{call<procedure-name>[<arg1>,<arg2>, ...]}
procedure-name:是所要执行的SQL存储过程的名字
[<arg1>,<arg2>, ...]:是相对应的SQL存储过程所需要的参数
ResultSetMeta接口
前面使用ResultSet接口类的对象来获取了查询结果集中的数据。
但ResultSet功能有限,如果我们想要得到诸如查询结果集中有多少列、列名称分别是什么就必须使用ResultSetMeta接口了。
ResultSetMeta是ResultSet的元数据。
元数据就是数据的数据, “有关数据的数据”或者“描述数据的数据”。
ResultSetMeta的使用
获得元数据对象
ResultSetMetaData rsmd=rst.getMetaData();
返回所有字段的数目
public int getColumCount() throwsSQLException
根据字段的索引值取得字段的名称
public String getColumName (int colum)throws SQLException
根据字段的索引值取得字段的类型
public String getColumType (int colum)throws SQLException
PreperedStatement接口和Statement的区别
(1) 使用Statement发送和执行sql语句
Statement stmt = con.creatStatement();//加载时,无参数,不编译sql语句
String sql = "selete * from emp";
ResultSet rs = stmt.executeQuery(sql);//执行时编译sql语句,返回查询结果集
(2) 使用PreparStatement发送和执行sql语句
String sql = "selete * from emp";
PreparStatement ps=con.prepareStatement(sql);//加载时就编译sql语句
ResultSet rs = ps.executeQuery();//此处执行时,不需要传参
还有就是
Statement stmt;支持可以通过字符串拼接(来传递参数),如StringdeleteStu = "delete from student where id="+id;但容易SQL注入
PreparedStatement ps; 不支持字符串拼接,提供?通配符传递参数,更安全;如String deleteStu = "delete from student where id=?";
ps.setInt(1, id); //设置第一个?通配值为id
事务
JDBC事务
何谓事务?
所谓事务是指一组逻辑操作单元,使数据从一种状态变换到另一种状态。
事务的ACID属性:
原子性(Atomicity):指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性(Consistency)事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
隔离性(Isolation)事务的隔离性是指一个事务的执行不能被其他事务干扰。
持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。
JDBC中使用COMMIT 和 ROLLBACK语句来实现事务。
COMMIT用于提交事务,ROLLBACK用于数据库回滚。
通过这两个语句可以确保数据完整性;数据改变被提交之前预览;将逻辑上相关的操作分组。
RollBack语句数据改变被取消使之再一次事务中的修改前的数据状态可以被恢复。
为了让多个 SQL 语句作为一个事务执行,基本步骤为:
先调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务。
然后在所有的 SQL 语句都成功执行后,调用 commit();
如果在出现异常时,可以调用 rollback();使方法回滚事务。
try{ conn.setAutoCommit(false);//不自动提交 sql //出问题 sql conn.commit();//提交 }e{ conn.rollback();回滚 }
JTA事务
在实际应用中经常会涉及到多个数据源的不同的连接,并且数据的操作要处于一个事务之中。
如去银行进行转账,转账的两个账户是不同的银行,当然数据的操作就跨数据库了,或者叫处于不同的数据源之中。
跨越多个数据源的事务,就要使用JTA容器实现事务。
在分布式的情况下的JTA容指的是Web容器,大家非常熟悉的Tomcat不能实现JTA的操作。
目前支持JTA的容器有非常著名的BEA公司的 Weblogic,IBM公司的WebSphere等企业级的Web应用服务器。
JTA分成两阶段提交
第一步,通过JNDI在分布式的环境中查找相关资源。
javax.transaction.UserTransactiontx = (UserTransaction)ctx.lookup(“jndiName");
tx.begin()
第二步,提交
tx.commit();
批处理:
url添加参数 ?rewriteBatchedStatements=true for(int i;i<1000;i++){ pstmt.setString(1, courseName); //给占位符赋值 pstmt.addBatch()//添加到批处理包 if(i%1000==0){ pstmt.executeBatch()//批量处理 pstmt.clearBatch()//清空处理包 } }
连接池:
c3p0
c3p0.jar
配置文件:c3p0.config.xml
//1. 将c3p0 提供的 c3p0.config.xml 拷贝到 src目录下 //2. 该文件指定了连接数据库和连接池的相关参数 ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("admin"); Connection connection = comboPooledDataSource.getConnection(); //这个方法就是从 DataSource 接口实现的 connection.close();
不用:
Properties properties = new Properties(); ... comboPooledDataSource.setDriverClass(driver); comboPooledDataSource.setJdbcUrl(url); comboPooledDataSource.setUser(user); comboPooledDataSource.setPassword(password); //设置初始化连接数 comboPooledDataSource.setInitialPoolSize(10); //最大连接数 comboPooledDataSource.setMaxPoolSize(50); Connection connection = comboPooledDataSource.getConnection(); //这个方法就是从 DataSource 接口实现的 connection.close();
德鲁伊druid
druid.jar
配置文件:druid.propertion
Properties properties = new Properties(); properties.load(new FileInputStream("src\\druid.properties")); //4. 创建一个指定参数的数据库连接池, Druid连接池 DataSource ds = DruidDataSourceFactory.createDataSource(properties); Connection connection = ds.getConnection();
工具类
String path = 当前类.class.getClassLoader().getResource("目标文件相对路径").getPath(); 获取到目标文件绝对路径;
普通工具类Util
package com.hl25.hspedu.jdbc.zuoye; import javax.naming.spi.DirectoryManager; import java.io.FileReader; import java.io.IOException; import java.net.DatagramPacket; import java.sql.*; import java.util.Properties; public class JDBCUtils { private static String url; private static String username; private static String password; private static String driver; //初始化 static { try { Properties properties = new Properties(); InputStream rps = JDBCUtils.class.getClassLoader().getResourceAsStream("com\\hpit11\\configuration_\\mysql.properties"); // properties.load(new FileReader("week1-code\\src\\com\\hpit11\\configuration_\\mysql.properties")); properties.load(rps); url = properties.getProperty("url"); username = properties.getProperty("user"); password = properties.getProperty("password"); driver = properties.getProperty("drover"); } catch (IOException e) { throw new RuntimeException(e); } } //连接数据库对象 public static Connection getConnection(){ try { return DriverManager.getConnection(url, username, password); } catch (SQLException throwables) { throw new RuntimeException(throwables); } } //关闭资源 public static void close(ResultSet set, PreparedStatement ps,Connection conn){ try { if (set!=null){ set.close(); } if (ps!=null){ ps.close(); } if (conn!=null){ conn.close(); } } catch (SQLException throwables) { throw new RuntimeException(throwables); } finally { } } }
配置文件:mysql.properties
user=root password=123456 url=jdbc:mysql://localhost:3306/initiation?rewriteBatchedStatements=true driver=com.mysql.jdbc.Driver
c3p0工具类Util
c3p0.jar
配置文件:c3p0.config.xml
public class JDBCUtilsByC3p0 { private static ComboPooledDataSource comboPooledDataSource ; static { Properties properties = new Properties(); try { comboPooledDataSource = new ComboPooledDataSource("admin"); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnertion() throws SQLException { return comboPooledDataSource.getConnection(); //这个方法就是从 DataSource 接口实现的 } public static void close(ResultSet rs, PreparedStatement ps, Connection conn) { try { if (rs != null) { rs.close(); } if (ps != null) { ps.close(); } if (conn != null) { conn.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } }
配置文件:c3p0.config.xml
<c3p0-config> <!-- 数据源名称代表连接池 --> <named-config name="admin"> <!-- 驱动类 --> <property name="driverClass">com.mysql.jdbc.Driver</property> <!-- url--> <property name="jdbcUrl">jdbc:mysql://localhost:3306/db4?rewriteBatchedStatements=true</property> <!-- 用户名 --> <property name="user">root</property> <!-- 密码 --> <property name="password">123456</property> <!-- 每次增长的连接数--> <property name="acquireIncrement">5</property> <!-- 初始的连接数 --> <property name="initialPoolSize">10</property> <!-- 最小连接数 --> <property name="minPoolSize">5</property> <!-- 最大连接数 --> <property name="maxPoolSize">50</property> <!-- 可连接的最多的命令对象数 --> <property name="maxStatements">5</property> <!-- 每个连接对象可连接的最多的命令对象数 --> <property name="maxStatementsPerConnection">2</property> </named-config> </c3p0-config>
德鲁伊工具类Util
druid.jar
配置文件:druid.propertion
package com.hpit11.JDBCUtils; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.FileReader; import java.sql.*; import java.util.Properties; public class JDBCUtilsByDruid { private static DataSource ds; static { try { String path = com.hpit11.JDBCUtils.JDBCUtilsByDruid.class.getClassLoader().getResource("com/hpit11/configuration_/druid.properties").getPath(); Properties properties = new Properties(); properties.load(new FileReader(path)); ds = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } public static DataSource getDataSource() { return ds; } public static Connection getConnertion() { try { return ds.getConnection(); } catch (SQLException throwables) { throw new RuntimeException(throwables); } } public static void close(ResultSet rs, PreparedStatement ps, Connection conn) { try { if (rs != null) { rs.close(); } if (ps != null) { ps.close(); } if (conn != null) { conn.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } }
配置文件:druid.properties
#key=value driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/hsp_db02?rewriteBatchedStatements=true username=root password=hsp #initial connection Size initialSize=10 #min idle connecton size minIdle=5 #max active connection size maxActive=50 #max wait time (5000 mil seconds) maxWait=5000
BasicDAO高级工具类
package com.hpit11.data_access_object.dao; import com.hpit11.data_access_object.utils.JDBCUtilsByDruid; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; import java.sql.SQLException; import java.util.List; public class BasicDAO<T> { private QueryRunner qr = new QueryRunner(JDBCUtilsByDruid.getDataSource()); //DML public int update(String sql,Object... paramenters){ try { int update = qr.update(sql, paramenters); return update; } catch (SQLException throwables) { throw new RuntimeException(throwables); }finally { // JDBCUtilsByDruid.close(); } } //多行查询 public List<T> queryMulti(String sql,Class<T> clazz,Object... paramenters){ try { return qr.query(sql,new BeanListHandler<T>(clazz),paramenters); } catch (SQLException throwables) { throw new RuntimeException(throwables); }finally { // JDBCUtilsByDruid.close(); } } //单行查询 public T querySingle(String sql,Class<T> clazz,Object... paramenters){ try { return qr.query(sql,new BeanHandler<T>(clazz),paramenters); } catch (SQLException throwables) { throw new RuntimeException(throwables); }finally { // JDBCUtilsByDruid.close(); } } //单值 public Object queryScalar(String sql,Object... paramenters){ try { return qr.query(sql,new ScalarHandler(),paramenters); } catch (SQLException throwables) { throw new RuntimeException(throwables); }finally { // JDBCUtilsByDruid.close(); } } }
Apache-DBUtils
类Actor <===> 库Actor
这样的类称为:JavaBean||POJO||Domain
Apache-DBUtils
配置文件:commons-dbutils.jar
增删改查:
public static void main(String[] args){ QueryRunner queryRunner = new QueryRunner(JDBCUtilsByDruid.getDataSource()); try { int affectedRowI = queryRunner.update("insert into cat value (?,?,?,?);",3,"小灰",5.6,"2021-9-16"); int affectedRowU = queryRunner.update("update cat set name=? where id=?","小花",1); int affectedRowD = queryRunner.update("delete from cat where id=?",1); List<Cat> list = queryRunner.query("select * from cat",new BeanListHandler<>(Cat.class));//多行 //Actor actor = queryRunner.query(sql, new BeanHandler<>(Actor.class), 10);//单行 //Object obj = queryRunner.query(sql, new ScalarHandler(), 4);//单反单列 for (Cat cat :list) { System.out.println(cat); } } catch (SQLException throwables) { throwables.printStackTrace(); } }
案例解析:
package com.hpit11.hl25.hspedu.jdbc.datasource; package com.hl25.hspedu.jdbc.datasource; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; import org.junit.jupiter.api.Test; import java.sql.*; import java.util.ArrayList; import java.util.List; /** * @author 韩顺平 * @version 1.0 */ @SuppressWarnings({"all"}) public class DBUtils_USE { //使用apache-DBUtils 工具类 + druid 完成对表的crud操作 @Test public void testQueryMany() throws SQLException { //返回结果是多行的情况 //1. 得到 连接 (druid) Connection connection = JDBCUtilsByDruid.getConnection(); //2. 使用 DBUtils 类和接口 , 先引入DBUtils 相关的jar , 加入到本Project //3. 创建 QueryRunner QueryRunner queryRunner = new QueryRunner(); //4. 就可以执行相关的方法,返回ArrayList 结果集 //String sql = "select * from actor where id >= ?"; // 注意: sql 语句也可以查询部分列 String sql = "select id, name from actor where id >= ?"; // 老韩解读 //(1) query 方法就是执行sql 语句,得到resultset ---封装到 --> ArrayList 集合中 //(2) 返回集合 //(3) connection: 连接 //(4) sql : 执行的sql语句 //(5) new BeanListHandler<>(Actor.class): 在将resultset -> Actor 对象 -> 封装到 ArrayList // 底层使用反射机制 去获取Actor 类的属性,然后进行封装 //(6) 1 就是给 sql 语句中的? 赋值,可以有多个值,因为是可变参数Object... params //(7) 底层得到的resultset ,会在query 关闭, 关闭PreparedStatment */ /** * 分析 queryRunner.query方法: * public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException { * PreparedStatement stmt = null;//定义PreparedStatement * ResultSet rs = null;//接收返回的 ResultSet * Object result = null;//返回ArrayList * * try { * stmt = this.prepareStatement(conn, sql);//创建PreparedStatement * this.fillStatement(stmt, params);//对sql 进行 ? 赋值 * rs = this.wrap(stmt.executeQuery());//执行sql,返回resultset * result = rsh.handle(rs);//返回的resultset --> arrayList[result] [使用到反射,对传入class对象处理] * } catch (SQLException var33) { * this.rethrow(var33, sql, params); * } finally { * try { * this.close(rs);//关闭resultset * } finally { * this.close((Statement)stmt);//关闭preparedstatement对象 * } * } * * return result; * } */ List<Actor> list = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1); System.out.println("输出集合的信息"); for (Actor actor : list) { System.out.print(actor); } //释放资源 JDBCUtilsByDruid.close(null, null, connection); } //演示 apache-dbutils + druid 完成 返回的结果是单行记录(单个对象) @Test public void testQuerySingle() throws SQLException { //1. 得到 连接 (druid) Connection connection = JDBCUtilsByDruid.getConnection(); //2. 使用 DBUtils 类和接口 , 先引入DBUtils 相关的jar , 加入到本Project //3. 创建 QueryRunner QueryRunner queryRunner = new QueryRunner(); //4. 就可以执行相关的方法,返回单个对象 String sql = "select * from actor where id = ?"; // 老韩解读 // 因为我们返回的单行记录<--->单个对象 , 使用的Hander 是 BeanHandler Actor actor = queryRunner.query(connection, sql, new BeanHandler<>(Actor.class), 10); System.out.println(actor); // 释放资源 JDBCUtilsByDruid.close(null, null, connection); } //演示apache-dbutils + druid 完成查询结果是单行单列-返回的就是object @Test public void testScalar() throws SQLException { //1. 得到 连接 (druid) Connection connection = JDBCUtilsByDruid.getConnection(); //2. 使用 DBUtils 类和接口 , 先引入DBUtils 相关的jar , 加入到本Project //3. 创建 QueryRunner QueryRunner queryRunner = new QueryRunner(); //4. 就可以执行相关的方法,返回单行单列 , 返回的就是Object String sql = "select name from actor where id = ?"; //老师解读: 因为返回的是一个对象, 使用的handler 就是 ScalarHandler Object obj = queryRunner.query(connection, sql, new ScalarHandler(), 4); System.out.println(obj); // 释放资源 JDBCUtilsByDruid.close(null, null, connection); } //演示apache-dbutils + druid 完成 dml (update, insert ,delete) @Test public void testDML() throws SQLException { //1. 得到 连接 (druid) Connection connection = JDBCUtilsByDruid.getConnection(); //2. 使用 DBUtils 类和接口 , 先引入DBUtils 相关的jar , 加入到本Project //3. 创建 QueryRunner QueryRunner queryRunner = new QueryRunner(); //4. 这里组织sql 完成 update, insert delete //String sql = "update actor set name = ? where id = ?"; //String sql = "insert into actor values(null, ?, ?, ?, ?)"; String sql = "delete from actor where id = ?"; //老韩解读 //(1) 执行dml 操作是 queryRunner.update() //(2) 返回的值是受影响的行数 (affected: 受影响) //int affectedRow = queryRunner.update(connection, sql, "林青霞", "女", "1966-10-10", "116"); int affectedRow = queryRunner.update(connection, sql, 1000 ); System.out.println(affectedRow > 0 ? "执行成功" : "执行没有影响到表"); // 释放资源 JDBCUtilsByDruid.close(null, null, connection); } }
Spring-DBUtils
类Actor <===> 库Actor
这样的类称为:JavaBean||PoJO||Domain
配置文件:Spring
ccpppp
增删改查:
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDs()); int affectedRowI = jt.update("insert into emp value(?,?,?,?,?,?,?,?);",1014,"关羽",4,1005,"2021-2-2",6666,null,20); int affectedRowI = jt.update("delete from emp where id=?",1014); int affectedRowI = jt.update("update emp set salary = '10000' where id =?",1014); List<Emp> emps = template.query("select * from emp",new BeanPropertyRowMapper<Emp>(Emp.class));//多行 //Map<String, Object> map = template.queryForMap("select * from emp where id = 1001");//单行 //List<Map<String, Object>> list = template.queryForList("select * from emp");//多行输出没有换行 //Long aLong = template.queryForObject("select count(id) from emp", Long.class);//聚合函数|返回对象 //Admin admin = queryForObjectTest("select * from admin where username=? and password=?",Admin.class,?,?) for (Emp emp :list) { System.out.println(emp); }
案例:
public class JDBCTemplateDemo1 { JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDs()); int count = template.update("update emp set salary = '10000' where id =1024"); int count = template.update("INSERT INTO emp VALUES(1025,'西门大官人',4,1006,'1089-10-11','12000','10000',30)"); int count = template.update("delete from emp where id = 1025"); //4. 查询单行,将其封装为Map集合 queryForMap() @Test public void test4(){ Map<String, Object> map = template.queryForMap("select * from emp where id = 1001"); System.out.println(map); Set<Map.Entry<String, Object>> entries = map.entrySet(); for (Map.Entry<String, Object> entry : entries) { String key = entry.getKey(); Object value = entry.getValue(); System.out.println(key +"---"+value); } } // 5. 查询所有记录,将其封装为List queryForList() @Test public void test5(){ List<Map<String, Object>> list = template.queryForList("select * from emp"); System.out.println(list); } // 6. 查询所有记录,将其封装为Emp对象的List集合 //查询都用这种 @Test public void test7(){ List<Emp> emps = template.query("select * from emp", new BeanPropertyRowMapper<Emp>(Emp.class));//自动封装 /** * 1.采用无参构造创建Emp对象 * 2.采用set将数据库中每一行中,每一个字段对应的值,封装到实体类的属性上 */ System.out.println(emps); } //7. @Test public void test8(){ Emp emp = template.queryForObject("select * from emp", Long.class); System.out.println(aLong); } //7. 查询总记录数 @Test public void test8(){ Long aLong = template.queryForObject("select count(id) from emp", Long.class); System.out.println(aLong); } //单行 @Test public void test6(){ List<Emp> emps = template.query("select * from emp", new RowMapper<Emp>() { @Override public Emp mapRow(ResultSet rs, int i) throws SQLException { Emp emp = null; while (rs.next()) { int id = rs.getInt(1); String ename = rs.getString("ename"); int job_id = rs.getInt(3); int mgr = rs.getInt(4); Date joindate = rs.getDate("joindate"); double salary = rs.getDouble(6); double bonus = rs.getDouble(7); int dept_id = rs.getInt(8); emp = new Emp(id, ename, job_id, mgr, joindate, salary, bonus, dept_id); } return emp; } }); System.out.println(emps); } }
BasicDAO
类Actor <===> 库Actor
这样的类称为:JavaBean||PoJO||Domain
DAO:data access object数据访问对象
基于druid数据库连接池的工具类
CatDAO(DAO)
package com.hpit11.data_access_object.dao; import com.hpit11.data_access_object.domain.Cat; public class CatDAO extends BasicDAO<Cat>{ //1. 就有 BasicDAO 的方法 //2. 根据业务需求,可以编写特有的方法. }
BasicDAO(DAO)
package com.hpit11.data_access_object.dao; import com.hpit11.data_access_object.utils.JDBCUtilsByDruid; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; import java.sql.SQLException; import java.util.List; public class BasicDAO<T> { private QueryRunner qr = new QueryRunner(JDBCUtilsByDruid.getDataSource()); //DML public int update(String sql,Object... paramenters){ try { int update = qr.update(sql, paramenters); return update; } catch (SQLException throwables) { throw new RuntimeException(throwables); }finally { // JDBCUtilsByDruid.close(); } } //多行查询 public List<T> queryMulti(String sql,Class<T> clazz,Object... paramenters){ try { return qr.query(sql,new BeanListHandler<T>(clazz),paramenters); } catch (SQLException throwables) { throw new RuntimeException(throwables); }finally { // JDBCUtilsByDruid.close(); } } //单行查询 public T querySingle(String sql,Class<T> clazz,Object... paramenters){ try { return qr.query(sql,new BeanHandler<T>(clazz),paramenters); } catch (SQLException throwables) { throw new RuntimeException(throwables); }finally { // JDBCUtilsByDruid.close(); } } //单值 public Object queryScalar(String sql,Object... paramenters){ try { return qr.query(sql,new ScalarHandler(),paramenters); } catch (SQLException throwables) { throw new RuntimeException(throwables); }finally { // JDBCUtilsByDruid.close(); } } }
Cat(domain类)
package com.hpit11.data_access_object.domain; import java.util.Date; public class Cat { private Integer id; private String name; private Double weight; private Date date; public Cat() { } public Cat(Integer id, String name, Double weight, Date date) { this.id = id; this.name = name; this.weight = weight; this.date = date; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Double getWeight() { return weight; } public void setWeight(Double weight) { this.weight = weight; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } @Override public String toString() { return "Cat{" + "id=" + id + ", name='" + name + '\'' + ", weight=" + weight + ", date=" + date + '}'; } }
TestDAO(测试类)
package com.hpit11.data_access_object.test; import com.hpit11.data_access_object.dao.CatDAO; import com.hpit11.data_access_object.domain.Cat; import org.junit.jupiter.api.Test; import java.util.List; public class TestDAO { @Test public void testCatDAO() { //测试CatDAO 对cat的CRUD操作 CatDAO catDAO = new CatDAO(); //查询 List<Cat> cats = catDAO.queryMulti("select * from cat where id>=?", Cat.class, 1); for (Cat cat :cats) { System.out.println(cat); } //单行 Cat cat = catDAO.querySingle("select * from cat where id=?", Cat.class, 1); System.out.println(cat); //单值 Object ocat = catDAO.queryScalar("select name from cat where id=?", 1); System.out.println(ocat); //dml // int update = catDAO.update("insert into cat value(?,?,?,?);",4,"小何",6.6,"2021-9-22"); System.out.println(update > 0 ? "执行成功" : "执行没有影响表"); } }
JDBCUtilsByDruid(工具类)
package com.hpit11.hl25.hspedu.dao_.utils; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.FileInputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; /** * 基于druid数据库连接池的工具类*/ public class JDBCUtilsByDruid { private static DataSource ds; //在静态代码块完成 ds初始化 static { Properties properties = new Properties(); try { properties.load(new FileInputStream("src\\druid.properties")); ds = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } //编写getConnection方法 public static Connection getConnection() throws SQLException { return ds.getConnection(); } //关闭连接, 老师再次强调: 在数据库连接池技术中,close 不是真的断掉连接 //而是把使用的Connection对象放回连接池 public static void close(ResultSet resultSet, Statement statement, Connection connection) { try { if (resultSet != null) { resultSet.close(); } if (statement != null) { statement.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { throw new RuntimeException(e); } } }
折叠
连接的5种方式
实用:
//方式5 , 在方式4的基础上改进,增加配置文件,让连接mysql更加灵活 @Test public static void main(String[] args) throws Exception { //看 PreparedStatement类图 Scanner scanner = new Scanner(System.in); //让用户输入管理员名和密码 System.out.print("请输入管理员的名字: "); //next(): 当接收到 空格或者 '就是表示结束 String admin_name = scanner.nextLine(); // 老师说明,如果希望看到SQL注入,这里需要用nextLine System.out.print("请输入管理员的密码: "); String admin_pwd = scanner.nextLine(); //通过Properties对象获取配置文件的信息 Properties properties = new Properties(); properties.load(new FileInputStream("src\\mysql.properties")); //获取相关的值 String user = properties.getProperty("user"); String password = properties.getProperty("password"); String driver = properties.getProperty("driver"); String url = properties.getProperty("url"); //1. 注册驱动 Class.forName(driver);//建议写上 //2. 得到连接 Connection connection = DriverManager.getConnection(url, user, password); //3. 得到PreparedStatement //3.1 组织SqL , Sql 语句的 ? 就相当于占位符 String sql = "select name , pwd from admin where name =? and pwd = ?"; //3.2 preparedStatement 对象实现了 PreparedStatement 接口的实现类的对象 PreparedStatement preparedStatement = connection.prepareStatement(sql); //3.3 给 ? 赋值 preparedStatement.setString(1, admin_name); preparedStatement.setString(2, admin_pwd); //4. 执行 select 语句使用 executeQuery // 如果执行的是 dml(update, insert ,delete) executeUpdate() // 这里执行 executeQuery ,不要在写 sql ResultSet resultSet = preparedStatement.executeQuery(sql); //5. 使用while取出数据 while (resultSet.next()) { // 让光标向后移动,如果没有更多行,则返回false //Object object = resultSet.getObject(1);取对象 int id = resultSet.getInt(1); //获取该行的第1列 //int id1 = resultSet.getInt("id"); 通过列名来获取值, 推荐 String name = resultSet.getString(2);//获取该行的第2列 String sex = resultSet.getString(3); Date date = resultSet.getDate(4); System.out.println(id + "\t" + name + "\t" + sex + "\t" + date); } if (resultSet.next()) { //如果查询到一条记录,则说明该管理存在 System.out.println("恭喜, 登录成功"); } else { System.out.println("对不起,登录失败"); } //关闭连接 resultSet.close(); preparedStatement.close(); connection.close(); } }
不实用:
//方式1 @Test public void connect01() throws SQLException { Driver driver = new Driver(); //创建driver对象 String url = "jdbc:mysql://localhost:3306/initiation"; //将 用户名和密码放入到Properties 对象 Properties properties = new Properties(); //说明 user 和 password 是规定好,后面的值根据实际情况写 properties.setProperty("user", "root");// 用户 properties.setProperty("password", "123456"); //密码 Connection connect = driver.connect(url, properties); System.out.println(connect); connect.close(); } //方式2 @Test public void connect02() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException { //使用反射加载Driver类 , 动态加载,更加的灵活,减少依赖性 Class<?> aClass = Class.forName("com.mysql.jdbc.Driver"); Driver driver = (Driver)aClass.newInstance(); String url = "jdbc:mysql://localhost:3306/initiation"; //将 用户名和密码放入到Properties 对象 Properties properties = new Properties(); //说明 user 和 password 是规定好,后面的值根据实际情况写 properties.setProperty("user", "root");// 用户 properties.setProperty("password", "123456"); //密码 Connection connect = driver.connect(url, properties); System.out.println("方式2=" + connect); connect.close(); } //方式3 使用DriverManager 替代 driver 进行统一管理 //看方法4 @Test public void connect03() throws IllegalAccessException, InstantiationException, ClassNotFoundException, SQLException { //使用反射加载Driver Class<?> aClass = Class.forName("com.mysql.jdbc.Driver"); Driver driver = (Driver) aClass.newInstance(); //创建url 和 user 和 password String url = "jdbc:mysql://localhost:3306/initiation"; String user = "root"; String password = "123456"; DriverManager.registerDriver(driver);//注册Driver驱动 Connection connection = DriverManager.getConnection(url, user, password); System.out.println("第3种方式~ " + connection); connection.close(); }
SQL执行
创建Statement或者PreparedStatement接口,执行SQL语句
使用Statement接口(存在SQL注入不能用)
Statement接口创建之后,可以执行SQL语句,完成对数据库的增删改查。其中 ,增删改只需要改变SQL语句的内容就能完成,然而查询略显复杂。在Statement中使用字符串拼接的方式,该方式存在句法复杂,容易犯错等缺点,具体在下文中的对比中介绍。所以Statement在实际过程中使用的非常的少,所以具体的放到PreparedStatement那里给出详细代码。
字符串拼接方式的SQL语句是非常繁琐的,中间有很多的单引号和双引号的混用,极易出错。
Statement s = conn.createStatement();//创建对象 // 准备sql语句 // 注意: 字符串要用单引号' String sql = "insert into t_courses values(null,"+"'数学')"; //在statement中使用字符串拼接的方式,这种方式存在诸多问题 s.execute(sql);//执行 System.out.println("执行插入语句成功");
//SQL注入 SELECT * FROM admin where name = '1' OR 'AND pwd =' OR '1'='1'
使用PreparedStatement接口(预处理)
与 Statement一样,PreparedStatement也是用来执行sql语句的与创建Statement不同的是,需要根据sql语句创建PreparedStatement。除此之外,还能够通过设置参数,指定相应的值,而不是Statement那样使用字符串拼接。
说明:
主要是SQL语句存在差异,其他的地方几乎是完全相同的。其中有几个地方需要注意:
使用PreparedStatement时,他的SQL语句不再采用字符串拼接的方式,而是采用占位符的方式。“?”在这里就起到占位符的作用。这种方式除了避免了statement拼接字符串的繁琐之外,还能够提高性能。每次SQL语句都是一样的,java类就不会再次编译,这样能够显著提高性能。 String sql = "update t_course set course_name =? where course_id=?"; 后面需要用到PreparedStatement接口创建的pstmt的set方法给占位符进行赋值。注意一点,这里的参数索引是从1开始的。
pstmt = (PreparedStatement) conn.prepareStatement(sql); pstmt.setString(1, courseName); //利用Preparedstatement的set方法给占位符赋值 pstmt.setInt(2, courseId); pstmt.executeUpdate();
/** * 添加课程 * @param courseName 课程名称 */ public void addCourse(String courseName){ String sql = "insert into t_course(course_name) values(?)"; //该语句为每个 IN 参数保留一个问号(“?”)作为占位符 Connection conn = null; //和数据库取得连接 PreparedStatement pstmt = null; //创建statement try{ conn = DriverManager.getConnection(url, user, password); pstmt = (PreparedStatement) conn.prepareStatement(sql); pstmt.setString(1, courseName); //给占位符赋值 pstmt.executeUpdate(); //执行 }catch(SQLException e){ e.printStackTrace(); } finally{ pstmt.close(); conn.close(); //必须关闭 } }
(可跳过)对数据库中的课程进行删除:
/*** 删除课程*/ public void delCourse(int courseId){ String sql = "delete from t_course where course_id = ?"; Connection conn = null; PreparedStatement pstmt = null; try { conn = DriverManager.getConnection(url, user, password);//连接 pstmt = (PreparedStatement) conn.prepareStatement(sql);//创建对象 pstmt.setInt(1, courseId);//给占位符赋值 pstmt.executeUpdate();//执行 } catch (SQLException e) { // TODO: handle exception e.printStackTrace(); }finally{ pstmt.close(); conn.close(); //必须关闭 } }
(可跳过)对数据库中的课程进行修改:
/** * 修改课程 * @param courseId * @param courseName */ public void modifyCourse(int courseId,String courseName){ String sql = "update t_course set course_name =? where course_id=?"; Connection conn = null; PreparedStatement pstmt = null; try { conn = DriverManager.getConnection(url, user, password); pstmt = (PreparedStatement) conn.prepareStatement(sql); pstmt.setString(1, courseName); //利用Preparedstatement的set方法给占位符赋值 pstmt.setInt(2, courseId); pstmt.executeUpdate(); } catch (SQLException e) { // TODO: handle exception e.printStackTrace(); }finally{ pstmt.close(); conn.close(); //必须关闭 } }
增删改都使用pstmt.executeUpdate();语句进行SQL语句的提交 ,下文的查询会有所不同,请注意。
在添加的过程的,如果添加的数据量比较大的话,可以用批量添加。 PreparedStatement接口提供了相应的批量操作的方法。
for(int i=1;i<100;i++){ pstmt.setInt(1,8000+i); pstmt.setString(2,"赵_"+i); pstmt.addBatch(); //批量更新 if(i%10==0){ pstmt.executeBatch(); } }
麻烦查询:
/** * 查询课程 * @return */ public List<Course> findCourseList(){ String sql = "select * from t_course order by course_id"; Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; //创建一个集合对象用来存放查询到的数据 List<Course> courseList = new ArrayList<>(); try { conn = DbUtil.getConnection(); pstmt = (PreparedStatement) conn.prepareStatement(sql); rs = (ResultSet) pstmt.executeQuery(); while (rs.next()){ int courseId = rs.getInt("course_id"); String courseName = rs.getString("course_name"); //每个记录对应一个对象 Course course = new Course(); course.setCourseId(courseId); course.setCourseName(courseName); //将对象放到集合中 courseList.add(course); } } catch (SQLException e) { // TODO: handle exception e.printStackTrace(); }finally{ DbUtil.close(pstmt); DbUtil.close(conn); //必须关闭 } return courseList; }
查询操作使用executeQuery()进行更新。其他相关的问题放在第四步(处理和显示结果)中解释。
处理执行结果
ResultSet对象
ResultSet对象负责保存Statement执行后所产生的查询结果。
结果集ResultSet是通过游标来操作的。
游标就是一个可控制的、可以指向任意一条记录的指针。有了这个指针我们就能轻易地指出我们要对结果集中的哪一条记录进行修改、删除,或者要在哪一条记录之前插入数据。一个结果集对象中只包含一个游标。
//5. 使用while取出数据 while (resultSet.next()) { // 让光标向后移动,如果没有更多行,则返回false int id = resultSet.getInt(1); //获取该行的第1列 //int id1 = resultSet.getInt("id"); 通过列名来获取值, 推荐 String name = resultSet.getString(2);//获取该行的第2列 String sex = resultSet.getString(3); Date date = resultSet.getDate(4); System.out.println(id + "\t" + name + "\t" + sex + "\t" + date); }Apache-DBUtils
List<Actor> list = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1);//多行 System.out.println("输出集合的信息"); for (Actor actor : list) { System.out.print(actor); }
###
练习:CRUD
CREATE TABLE admin( name VARCHAR(32) NOT NULL UNIQUE, pws VARCHAR(32) NOT NULL DEFAULT '' ) CHARACTER SET utf8;
import java.io.FileReader; import java.io.IOException; import java.sql.*; import java.util.*; import com.hl25.CRUD; public static void main(String[] args) throws ClassNotFoundException, IOException, SQLException { Scanner sc = new Scanner(System.in); Properties properties = new Properties(); properties.load(new FileReader("src\\com\\hl25\\hspedu\\mysql.properties")); String url = properties.getProperty("url"); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String driver = properties.getProperty("driver"); Class.forName("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection(url, user, password); //添加 // insert(connection, sc); // CRUD.insert(connection, "elle", "111111"); //删除 // delete(connection, sc); //修改 // alterupdata(connection, sc); //查找 // select(connection, sc); //查找全部 selectall(connection); } //添加 public static void insert(Connection connection,Scanner sc) throws SQLException { System.out.println("需要添加的用户名:"); String name = sc.next(); System.out.println("密码:"); String psw = sc.next(); String sqli = "insert into admin values(?,?)"; PreparedStatement prsm = connection.prepareStatement(sqli); prsm.setString(1, name); prsm.setString(2, psw); prsm.executeUpdate(); } //删除 public static void delete(Connection connection,Scanner sc) throws SQLException { System.out.println("需要删除的用户名:"); String name = sc.next(); System.out.println("请输入密码:"); String psw = sc.next(); String sqld = "delete from admin where name=? and pws=?"; PreparedStatement prsm = connection.prepareStatement(sqld); prsm.setString(1, name); prsm.setString(2, psw); prsm.executeUpdate(); } //修改 public static void alterupdata(Connection connection,Scanner sc) throws SQLException { System.out.println("需要修改的用户名:"); String name = sc.next(); System.out.println("请输入密码:"); String psw = sc.next(); System.out.println("新的用户名:"); String newname = sc.next(); System.out.println("新的密码:"); String newpsw = sc.next(); String sqlu = "update admin set name=?,pws=? where name=? and pws=? "; PreparedStatement prsm = connection.prepareStatement(sqlu); prsm.setString(1, newname); prsm.setString(2, newpsw); prsm.setString(3, name); prsm.setString(4, psw); prsm.executeUpdate(); } //查找 public static void select(Connection connection,Scanner sc) throws SQLException { System.out.println("需要查找的用户名:"); String name = sc.next(); System.out.println("请输入密码:"); String psw = sc.next(); String sqls = "select * from admin where name=? and pws=?"; PreparedStatement prsm = connection.prepareStatement(sqls); prsm.setString(1, name); prsm.setString(2, psw); ResultSet resultSet = prsm.executeQuery(); HashMap<String,String> map = new HashMap<>(); while (resultSet.next()){ String names = resultSet.getString("name"); String psws = resultSet.getString("pws"); map.put(names, psws); } System.out.println(map); } //查找所有 public static void selectall(Connection connection) throws SQLException { String sqls = "select * from admin "; PreparedStatement prsm = connection.prepareStatement(sqls); ResultSet resultSet = prsm.executeQuery(); HashMap<String,String> map = new HashMap<>(); while (resultSet.next()){ String names = resultSet.getString("name"); String psws = resultSet.getString("pws"); map.put(names, psws); } System.out.println(map); }
Properties
Properties properties = new Properties();
配置:
路径: String path = com.hpit11.JDBCUtils.JDBCUtilsByDruid.class.getClassLoader().getResource("com/hpit11/configuration_/druid.properties").getPath(); 读取流: properties.load(new FileReader(path); 流路径加载: InputStream ras = com.hpit11.JDBCUtils.JDBCUtilsByDruid.class.getClassLoader().getResourceAaStream("com/hpit11/configuration_/druid.properties"); 读取流: properties.load(ras);