700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > -3-28 JDBC入门包含数据库连接池

-3-28 JDBC入门包含数据库连接池

时间:2020-06-12 23:14:01

相关推荐

-3-28 JDBC入门包含数据库连接池

里面的数据库连接池所需要的jar包可以在这里面下载:

/m0_49647974/article/details/115287069

文章目录

一.概念:Java DataBase Connectivity二.具体流程:三. 代码实现四.详解各个对象:1.DriverManager :驱动管理对象(1)注册驱动:(2)获取数据库连接:2.Connection :数据库连接对象(1)获取执行中的sql对象(2)管理事务3.Statement :执行sql的对象4.Resultset :结果集对象5.Preparedstatement :执行sql的对象五、数据库连接池1.标准接口:DataSourcejavax.sql包下的2.数据库厂商实现:3.C3P0:数据库连接池技术4.Druid:数据库连接池实现技术(阿里巴巴)六.Spring JDBC记录:学习中遇到的一些bug1.JDBC连接时错误:closing inbound before receiving peer's close_notify2.JDBC连接时错误:3.C3P0数据库连接池报错:An attempt by a client to checkout a Connection has timed out.4.警告: Cannot resolve com.mysq.jdbc.Connection.ping method. Will use 'SELECT 1' instead.

一.概念:Java DataBase Connectivity

Java 数据库连接,Java语言操作数据库

JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

二.具体流程:

(1)导入驱动jar包 如:mysql-connector-java-5.1.37-bin.jar

复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下右键–>Add As Library

(2)注册驱动

(3)获取数据库连接对象connection4.

(4)定义sql

(5)获取执行sql语句的对象statement6.

(6)执行sq1,接受返回结

(7)处理结果

(8)释放资源

三. 代码实现

/*** @Auther: Parsifal* @Date: /03/22/20:04* @Description:*/public class JDBCTest {public static void main(String[] args) {Connection connection = null;Statement statement = null;try {//1、导入驱动jar包//2、注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//3、获取数据库连接对象String userName = "root";String password = "root";//报错一:The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to util// 解决方法与原因:当mysql和connector版本八以上时,系统时区错误,需要在配置连接数据库的url加上:?serverTimezone=GMT%2B8// 报错二: .ssl.SSLException: closing inbound before receiving peer's close_notify//解决方法:需要在配置连接数据库的url加上: &useSSL=falseconnection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useSSL=false", userName, password);//4、定义sql语句String sql = "SELECT * FROM student";//5、获取执行sql的对象、Statementstatement = connection.createStatement();boolean execute = statement.execute(sql);//6、处理结果System.out.println(execute);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException throwables) {throwables.printStackTrace();} finally {//7、关闭资源if (statement!=null){try {statement.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (connection!=null){try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}}}

但是我们一般都会把这些代码封装成一个Util,把数据库信息写在配置文件里面,如下:

/*** @Auther: Parsifal* @Date: /03/24/21:24* @Description:*/public class JDBCUtil {private static String url;private static String user;private static String password;private static String driver;//静态模块会在类加载时执行static {FileInputStream fileInputStream = null;try {//properties处理属性文件//获取src路径下的文件的方式一(stream)Properties properties = new Properties();fileInputStream = new FileInputStream("jdbc.properties");//加载流对应的文件properties.load(fileInputStream);//获取src路径下的文件的方式二(path)/* ClassLoader classLoader = JDBCUtil.class.getClassLoader();URL resource = classLoader.getResource("jdbc.properties");String path = resource.getPath(); //获取绝对路径System.out.println(path);properties.load(new FileReader(path));*/url = properties.getProperty("url");user = properties.getProperty("user");password = properties.getProperty("password");driver = properties.getProperty("driver");Class.forName(driver);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();} finally {if (fileInputStream!=null){try {fileInputStream.close();} catch (IOException e) {e.printStackTrace();}}}}public static Connection getConnection(){try {return DriverManager.getConnection(url,user,password);} catch (SQLException throwables) {throwables.printStackTrace();}return null;}//关闭资源public static void close(Statement statement, Connection connection, ResultSet resultSet){if (statement!=null){try {statement.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (connection!=null){try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}if (resultSet!=null){try {resultSet.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}}//关闭资源 重载方法public static void close(Statement statement, Connection connection){if (statement!=null){try {statement.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (connection!=null){try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}}

jdbc.properties配置文件

url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useSSL=falseuser=rootpassword=rootdriver=com.mysql.cj.jdbc.Driver

四.详解各个对象:

1.DriverManager :驱动管理对象

(1)注册驱动:

​ static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。

​ 写代码使用: class.forName(“com.mysql.jdbc.Driver”); 把此类加载进内存。

​(注意:在mysql5之后的驱动jar包可以省略注册驱动的步骤)

​ 在com.mysql.jdbc.Driver类中存在以下静态代码块,在类加载时运行创建Driver类。

static {try {DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException("Can't register driver!");}}

(2)获取数据库连接:

方法:DriverManager.getConnection(“jdbc:mysql://localhost:3306/test”, userName, password);

参数

url:指定连接路径 : jdbc:mysql:// ip地址(域名): 端口 /数据库名称

用 " ?"在url后边可以添加属性,”&”可以连接不同的属性,以下举例一些属性:

​ serverTimezone=GMT mysql8版本以上要加上,作用为调整时区

​ allowMultiQueries=true,支持mybatis执行多条语句;

​ useSSL=false,是否进行ssl连接,高版本可能需要设为true;

​ serverTimezone=UTC,设置时区

uersName:用户名称,password:密码。

注意如果是本机mysql服务器,并且mysql服务默认端口为3306,则url可以不写(jdbc:mysql:///test)

2.Connection :数据库连接对象

(1)获取执行中的sql对象

Statement createStatement() 创建Statement对象PreparedStatement preparedStatement(String sql)

(2)管理事务

事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败

为什么要使用事务?

首先我们先了解没有事务的时候:如果不通过事务方式管理SQL语句。此时的SQL语句的提交(commit),是由驱动程序负责管理,在SQL执行完后,就会自动帮我们进行提交,每一条SQL都相当于一个事务。但是执行多条相关联SQL语句,而不通过事务来管理时。如果再某些步骤中中止或操作失误,就会破坏数据库的一致性。(如下,由于没有通过事务sql,我有两条sql语句修改两个内容,当第一条语句执行完后,中间遇到步骤终止和操作失误,会导致第二条sql无法执行。这是很严重的后果。)

步骤:

开启事务: setAutocommit(boolean autocommit):调用该方法设置参数为false,即开启事务提交事务: commit()回滚事务: rollback()

//JDBC事务@Testpublic void test2(){Connection connection = null;Statement statement = null;PreparedStatement preparedStatement1 =null;PreparedStatement preparedStatement2 =null;try {//获取连接connection = JDBCUtil.getConnection();//开启事务connection.setAutoCommit(false);//修改id=1的学生的绩点String sql1 = " update student set name='张三' where id= ? ";//修改id=2的学生的绩点String sql2 = "update student set name='李四' where id= ? ";preparedStatement1 = connection.prepareStatement(sql1);preparedStatement2 = connection.prepareStatement(sql2);preparedStatement1.setInt(1,1);preparedStatement2.setInt(1,2);preparedStatement1.executeUpdate();//手动制造异常// int a =1/0;preparedStatement2.executeUpdate();//提交事务mit();} catch (Exception throwables) {try {//事务的回滚if (connection!=null) {connection.rollback();}} catch (SQLException e) {e.printStackTrace();}throwables.printStackTrace();} finally {JDBCUtil.close(preparedStatement1, connection);if (preparedStatement2!=null) {try {preparedStatement2.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}}

没有使用事务(两条语句中间手动制造异常,第一条语句执行)

使用事务同时无法执行(两条语句都无法执行)

3.Statement :执行sql的对象

执行sql语句 boolean execute(string sql):可以执行任意的sqlint executeUpdate(string sql)∶执行DML (insert、update、delete)语句、DDL(对表和库的操作如:create,alter,drop)语句 该方法的返回值是影响的行数、如果返回值>0则执行成功,反之,则失败 Resultset executeQuery(string sql)︰执行DQL (select)语句

4.Resultset :结果集对象

常用方法:

boolean next():游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回truegetxxx(参数):获取数据xxx:代表数据类型如: int getInt() , string getstring() int : 代表列的编号,从1开始如:getstring(1)String :代表列名称。如: getDouble(“email”)如图:getString(1)与getDouble(“id”)是同一个值

5.Preparedstatement :执行sql的对象

作用:预编译sql语句防止恶意sql注入

SQL注入问题∶在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题

输入用户随便,输入密码:a’ or "a’ = 'asql : select * from user where username = 'fhdsjkf’ and password = ‘a’ or ‘a’ = ‘a’

使用方法:

(1)使用 ?占位符写sql(如 :select * from student where id = ?and grade=?)

(2)获取执行sql语句的对象Preparedstatement Connection.prepareStatement(String sql)

(3)给?赋值:格式preparedstatement.setXxx(参数1,参数2) ==>参数1:?的位置,参数2:?的值

(4)执行sql,接受返回结果,不需要传递sql语句

@Testpublic void test1(){Connection connection = null;PreparedStatement preparedStatement =null;try {connection = JDBCUtil.getConnection();//使用 ?占位符写sqlString sql = "select * from student where id = ? and grade=? ";//给?赋值preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,1);preparedStatement.setFloat(2,3.5f);ResultSet resultSet = preparedStatement.executeQuery();//处理结果while (resultSet.next()) {int id = resultSet.getInt("id");String name = resultSet.getString("name");String email = resultSet.getString("email");double grade = resultSet.getDouble("grade");System.out.println(id + name + email + grade); //结果:1 zzz 564894525@ 3.5}} catch (SQLException throwables) {throwables.printStackTrace();} finally {JDBCUtil.close(preparedStatement, connection);}}

五、数据库连接池

概念::其实就足一个容器(集合),存放数据库连接的容器。当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

好处:

节约资源用户访问高效

实现:

1.标准接口:DataSourcejavax.sql包下的

方法∶ 获取连接:getConnection()归还连接:connection.close()。如果连接对貌Connection是从连接池中获取的,那么调用connection.close()方法,则不会再关闭连接了。而是归还连接

2.数据库厂商实现:

C3P0:数据库连接池技术Druid:数据库连接池实现技术(阿里巴巴)

3.C3P0:数据库连接池技术

导入jar两个 c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar定义配置文件: 名称:c3p0.properties 或者 c3p0-config.xml (注意:C3P0只能识别这两个配置文件)路径:直接接将文件放在src目录下即可。 创建核心对象数据库连接池对象comboPooledDataSource获取连接: getConnection

/*** @Auther: Parsifal* @Date: /03/27/20:38* @Description: C3P0的演示*/public class C3P0Test {public static void main(String[] args) throws SQLException {// 1、创建数据库连接池对象 ->使用默认配置// DataSource ds = new ComboPooledDataSource();//使用指定配置DataSource ds = new ComboPooledDataSource("otherc3p0");// 2、获取连接对象Connection conn = ds.getConnection();System.out.println(conn);conn.close();}

<?xml version="1.0" encoding="utf-8"?> <c3p0-config><!-- 使用默认的配置读取连接池对象--><default-config><!-- 连接参数--><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&amp;useSSL=false</property><property name="user">root</property><property name="password">root</property><!-- 连接池参数--><!-- 初始化申请的连接数量--><!-- 初始化五个Connection对象--><property name="initialPoolSize">5</property><!-- 最大连接数量--><property name="maxPoolSize">10</property><!-- 如果申请不到,最多会等待三秒--><property name="checkoutTimeout">3000</property></default-config><named-config name="otherc3p0"> </named-config></c3p0-config>

4.Druid:数据库连接池实现技术(阿里巴巴)

导人jar包druid-1.o.9.jar定义配置i文件: 可以叫任何名称,可以放在任何目录下是properties形式的 获取数据库连接池对象∶通过工厂来来获取DruidDataSourceFactory获取连接∶getConnection

实现代码:

package DateSource;import DateSource.Druid.DruidTest;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;import java.io.IOException;import java.io.InputStream;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Properties;/*** @Auther: Parsifal* @Date: /03/27/22:22* @Description: 使用Druid数据库连接池的JDBCUtil*/public class JDBCUtil {static DataSource ds;static {//加载配置文件try {//1、导入jar包//2、定义配置文件//3、加载配置文件 不可以默认配置文件 ,必须指定文件Properties properties =new Properties();InputStream is = DruidTest.class.getClassLoader().getResourceAsStream("druid.properties");properties.load(is);//4、获取数据库连接池对象ds = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}/*** 获取连接* @return* @throws SQLException*/public static Connection getConnection() throws SQLException {return ds.getConnection();}/*** 关闭资源* @param resultSet* @param statement* @param connection*/public static void close(ResultSet resultSet, Statement statement, Connection connection){if (resultSet!=null){try {resultSet.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (statement!=null){try {statement.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (connection!=null){try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}/*** 重载* @param statement* @param connection*/public static void close(Statement statement ,Connection connection){close(null,statement,connection);}/*** 获取数据库连接池* @return*/public static DataSource getDataSource(){return ds;}}

六.Spring JDBC

spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发步骤︰

步骤:

导入四个jar包 spring-tx-5.0.5.RELEASE.jar spring-jdbc-5.0.5.RELEASE.jar spring-core-5.0.5.RELEASE.jar spring-beans-5.0.5.RELEASE.jar commons-logging-1.2.jar

创建JdbcTemplate对象。依赖于数据源Datasource

调用JdbcTemplate的方法来完成CRUD的操作

update():执行DML语句。增、删、改语句

queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value将这条记录封装为一个map集合

注意:这个方法查询的结果集长度只能是1

queryForList():查询结果将结果集封装为list集合

注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中

query():查询结果,将结果封装为javaBean对象

注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中

query的参数:RowMapper

一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装newBeanPropertyRowMapper<类型>(类型.class)

queryForobject :查询结果,将结果封装为对象

/*** @Auther: Parsifal* @Date: /03/28/14:12* @Description:*/public class JDBCTemplateTest {//1、导入jar//2、创建JDBCTemplate对象static JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtil.getDataSource());//查询所有的记录用List集合@Testpublic void test(){String sql = "select * from student";//自定义接口List<Student> students = jdbcTemplate.query(sql, new RowMapper<Student>() {@Overridepublic Student mapRow(ResultSet resultSet, int i) throws SQLException {int id = resultSet.getInt("id");String name = resultSet.getString("name");String email = resultSet.getString("email");float grade = resultSet.getFloat("grade");Student student = new Student(id,name,email,grade);return student;}});students.forEach(System.out::println);}//查询所有的记录用List集合@Testpublic void test1(){String sql = "select * from student";//使用封装好的接口List<Student> students = jdbcTemplate.query(sql,new BeanPropertyRowMapper<Student>(Student.class));students.forEach(System.out::println);}}

记录:学习中遇到的一些bug

mysql版本号为8.0.13

1.JDBC连接时错误:closing inbound before receiving peer’s close_notify

解决方法与原因:配置连接数据库的url错误,在后面加上&useSSL=false即可

2.JDBC连接时错误:

The server time zone value ‘Öйú±ê׼ʱ¼ä’ is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to util

解决方法与原因:当mysql和connector版本八以上时,系统时区错误,需要在配置连接数据库的url加上:?serverTimezone=GMT%2B8

3.C3P0数据库连接池报错:An attempt by a client to checkout a Connection has timed out.

解决方法与原因:配置文件的url错误(并且注意:&需要转义为&)

<property name="jdbcUrl">jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&amp;useSSL=false</property>

顺便说一下:可以试试看其他的解决方法:

重启mysql服务

<property name="checkoutTimeout">3000</property> 改大等待时间

<property name="maxPoolSize">10</property> 改小最大连接数量

4.警告: Cannot resolve com.mysq.jdbc.Connection.ping method. Will use ‘SELECT 1’ instead.

解决方法与原因:druid版本与mysql版本不兼容,更换druid版本1.1.21即可

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。