一,对JDBC的认识
Jdbc是一个持久层技术,它特定独立于数据库管理系统,通用的sql数据库存储操作的公共api,是访问数据库的一种规范和标准的接口,定义了java访问数据库的标准类库(如java.sql,javax.sql),jdbc可以方便访问数据库并操作数据库,jdbc也在其他语言中有同样的作用
jdbc带来的好处:
1,jdbc为访问不同sql数据库提供了统一的途径(通过jdbc可以访问MySQL和oracle等数据库)
2,jdbc屏蔽了底层细节,简化了开发过程
假如没有jdbc我们访问数据库:
我们要根据不同数据库类型,写一个驱动程序,过程复杂,门槛高
jdbc的两类接口:
1,程序操作的API接口:这是面向开发者的接口(开发者根据这是接口实现对数据库的操作)
2,数据库的驱动接口Driver:这是面向数据库厂商的接口(厂商根据jdbc提供的标准开发驱动Driver,实现不同数据库的复用性)
jdbc是持久层框架的基础:
mybatis就是基于jdbc的对象关系型映射框架,还有Hibernate框架……
二,jdbc的操作
jdbc的操作主要是连接+增删改查
一,数据库连接方式
jdbc的数据库的连接方式其实是固定的:注册驱动 -> 通过配置信息建立连接
1,直接创建Driver对象
Driver API
String div="jdbc:mysql://localhost:3306/wql"; Driver driver=new com.mysql.jdbc.Driver(); //直接new Driver对象,耦合度高直接依赖于MySQLjar包 Properties info =new Properties(); info.put("user", "root"); info.put("password", "123"); Connection connection=driver.connect(div, info); System.out.print(connection); connection.close();
2,反射创建Driver对象
通过class反射创建对象
class API
Driver driver=(Driver) Class.forName("com.mysql.jdbc.Driver").newInstance();//其实没必要这样,forname返回的是静态类,直接调用就行 String con="jdbc:mysql://localhost:3306/WQL"; Properties properties=new Properties(); properties.setProperty("user", "root"); properties.setProperty("password", "123"); Connection connection=driver.connect(con,properties); connection.close(); System.out.print(connection);
3,DriverManager管理类创建连接(常用)
Manager是驱动的管理类可以创建连接,也可以操作其他信息
Driver API
String dirver="com.mysql.jdbc.Driver"; String connection="jdbc:mysql://localhost:3306/WQL"; Class.forName(dirver); Connection conn=DriverManager.getConnection(connection, "root", "123");//也可以转一个properties对象 conn.close(); System.out.print(conn);
4,外部配置文件建立连接
把配置参数写入文件中,在文件中配置修改信息,降低耦合,增加重用性
1,建立一个wql.propertise文件
user=root password=123 Driver=com.mysql.jdbc.Driver connection=jdbc:mysql://localhost:3306/WQL
2,将文件信息读取建立连接
//定义变量 String user=null; String password=null; String driver=null; String connection=null; //读取配置文件 FileInputStream input=new FileInputStream("wql.properties"); //读取文件流 Properties properties=new Properties(); properties.load(input); user = properties.getProperty("user"); password = properties.getProperty("password"); driver = properties.getProperty("Driver"); connection=properties.getProperty("connection"); //连接 Driver d = (Driver) Class.forName(driver).newInstance(); Properties properties1=new Properties(); properties1.setProperty("user", user); properties1.setProperty("password", password); Connection conn=d.connect(connection,properties1); //测试连接是否有效 System.out.print(conn); conn.close();
二,Statement操作数据库
statement是jdbc的操作数对象之一,通过它可以实现对数据的DML操作
一,statement的获取
通过connection连接获取statement对象
Statement statement=conn.createStatement();
二,数据的插入和修改
插入和修改操作都依赖execte方法,在statement操作只能通过sql语句的字符串拼接来实
sql语句的拼接对资源是一种极大的消耗,批量插入或者修改时,字符串都必须重新组装,浪费时间和内存
三,数据的查询
查询依赖executeQuery方法,它返回一个Resultset对象,通过遍历Resultset对象可以查询结果
Statement statemend=conn.createStatement(); String sql="select * from "+tablename; ResultSet resultset=statemend.executeQuery(sql); ArrayList<String[]> list=new ArrayList<>(); while(resultset.next()) { Integer id= resultset.getInt(1); String name= resultset.getString(2); Integer random= resultset.getInt(3); String[] wql=new String[3]; wql[0]=id.toString(); wql[1]=name; wql[2]=random.toString(); list.add(wql); } Iterator l= list.iterator(); while(l.hasNext()) { String[] a=(String[]) l.next(); for(String aq:a) { System.out.print(aq+"\t"); } System.out.println(); } close(statemend); resultset.close();
三,PreparedStatement操作数据库
preparedstatement严格上它是statement的子类,它是在statement上的弊端的补全和结构的优化
preparedstatement最大的改良就是把statement的sql字符串拼接改成了参数注入,实现了预编译sql语句,sql语句被预编译进入prepaoedstatement对象中,使用这个对象可以高效的重复执行操作
一,创建preparedstatement对象
connection创建preparedstatement的API
String sql="insert into "+tablename+" values(?,?,?)"; PreparedStatement s=(PreparedStatement) conn.prepareStatement(sql);
二,数据的插入和修改
String sql="insert into "+tablename+" values(?,?,?)"; PreparedStatement s=(PreparedStatement) conn.prepareStatement(sql); // System.out.print(sql); s.setInt(1, 7); s.setString(2, "las"); s.setInt(3, 100); s.executeUpdate();//执行语句 close(s); s.close();
三,数据查询
String sql="select * from ?"; PreparedStatement s= conn.prepareStatement(sql); s.setString(1, "test"); ResultSet ss= s.executeQuery(sql); while(ss.next()) { System.out.print(ss.getString(2)+"===="+ss.getInt("id")); }
四,statement和preparedstatement的比较
两者区别主要是从安全性和效率两个方面比较:
1,安全性:前者sql的执行主要是通过字符串拼接实现的,容易产生sql注入,而后者是预编译在方法内部运行,不会产生注入问题
2,效率:字符串的拼接本身也是极其浪费资源的,批量操作每一次执行都需要拼接一次字符串浪费了资源,后者预编译sql,可以高效重复执行
一,SQL注入问题
通过字符串的拼接原理,人为产生一个新sql
Statement statement=conn.createStatement(); //注入语句 String sql1="where id>100"; //正常语句 String sql="select * from test"; //注入sql statement.executeQuery(sql+sql1);
二,批量操作
批量操作的几种方式:
1,statement实现
2,preparedstatement实现
3,addbatch缓冲池实现
//批量插入数据 public static void main(String[] args) throws Exception { jdbctool c=new jdbctool(); Connection conn = c.getconn(); long a= System.currentTimeMillis(); test3(conn); long a1=System.currentTimeMillis(); System.out.print((a1-a)/1000); } //方式1:statement,字符串拼接 public static void test1(Connection conn) throws SQLException { Statement statement=conn.createStatement(); for(int a=2;a<=100000;a++) { String sql="insert into test values ("+a+","+a+")"; statement.execute(sql); } statement.close(); conn.close(); //花费时间:73秒 } //方式2:preparedstatement public static void test2(Connection conn) throws SQLException { String sql="insert into test values (?,?)"; PreparedStatement prepared =conn.prepareStatement(sql); for(int i=2;i<=100000;i++) { prepared.setInt(1, i); prepared.setString(2,""+i); prepared.execute(); } prepared.close(); conn.close(); //花费时间:53秒 } //方式3:preparedstatement的addbatch缓冲池(相当于io的buffer缓存区) //注:在sql中默认一条语句就是一个事务直接提交,用缓冲区我们不要自动提交,设置为手动提交(?rewriteBatchedStatements=true加在url配置后面) public static void test3(Connection conn) throws SQLException { String sql="insert into test values (?,?)"; PreparedStatement prepared =conn.prepareStatement(sql); for(int i=2;i<=100000;i++) {//多了个0 prepared.setInt(1, i); prepared.setString(2, ""+i); //加入缓冲区 prepared.addBatch(); if(i%50000==0) { prepared.executeBatch(); prepared.clearBatch(); } } prepared.close(); conn.close(); //花费时间:34秒 }
三,Blob类型数据的插入
Blob类型数据算是MySQL中一种有意思的数据类型
blob类型介绍:
1,blob类型是MySQL中一种二进制大型对象,是一个存储大型数据的容器,它能容纳不同大小的数据(像图片和音频)
2,插入blob对象必须要使用PreparedStatement对象,因为它不能通过字符串拼接得到(它的输入有两种:输入io流,blob对象)
3,MySQL中有四种blob类型(除最大容量不同,其他一致)
类型 大小(单位:字节) TinyBlob 最大255 Blob 最大65k MediumBlob 最大16M LongBlob 最大4G
注:如果过大数据库性能会下降,超过容量会报错
PreparedStatement插入blob API:
Connection conn=null; jdbctool tool=new jdbctool(); conn=tool.getconn(); PreparedStatement prepared = conn.prepareStatement("insert into blobs values (?,?)"); InputStream wql = new FileInputStream(new File("4-1.jpg")); prepared.setInt(1, 1); prepared.setBlob(2, wql); prepared.execute(); prepared.close(); conn.close();
三,数据库连接池
数据库连接创建和关闭读极其耗费资源,而数据库连接池就很好的弥补了这个缺陷,连接池提高了连接的重用性
连接池的作用:
1,统一管理连接创建和销毁,减少资源的占用
2,连接的可重用性提高,提高的程序效率
连接池三种类型jar包下载:
DataSource接口(重点):
这是java提供,数据库连接池的必须实现的一个接口,主要由数据库厂商实现
而DataSource又继承ConnomDatasource方法
常用的连接池框架(主要介绍三种):
1,C3P0:是一个开源组织提供的数据库连接池,速度较慢,但稳定性较好
2,DBCH:Apache提供是Tomcat自带的数据库连接池,相比较C3P0快,当自身有bug
3,Druid:是阿里的连接池,集成了各数据库连接池的优点(是现在主流)
一,C3P0
第一种实现(手写配置):
//获取c3p0连接池, ComboPooledDataSource pool= new ComboPooledDataSource(); //基本参数设置 pool.setDriverClass("com.mysql.jdbc.Driver"); pool.setJdbcUrl("jdbc:mysql://localhost/wql"); pool.setUser("root"); pool.setPassword("123"); //获取连接 Connection conn=pool.getConnection(); System.out.print(conn);
第二种实现(配置文件配置):
这里配置文件可以是prepaoties文件也可以是xml文件,以xml文件为例
新建一个xml文件:这个文件命名必须是c3p0默认配置文件名,c3p0-config.xml,c3p0有自己独特的xml风格
c3p0-config.xml:文件格式和配置信息详情,只是一部分
<?xml version="1.0" encoding="UTF-8"?> <!--c3p0根标签 --> <c3p0-config> <!--default-config 默认配置 只读取一次 --> <default-config> <!-- 连接超时时间 --> <property name="checkoutTimeout">30000</property> <!-- 每个多少秒检查池中的空闲连接 --> <property name="idleConnectionTestPeriod">30</property> <!-- 初始化连接池大小 --> <property name="initialPoolSize">10</property> <!-- 最大空闲时间,指定时间连接未使用,连接被丢弃 --> <property name="maxIdleTime">30</property> <!-- 设置最小和最大连接池连接数 --> <property name="maxPoolSize">100</property> <property name="minPoolSize">10</property> <property name="maxStatements">200</property> <!-- 每一个user用户可以当指定连接数和缓存PreparedStatement的总数 --> <user-overrides user="test-user"> <property name="maxPoolSize">10</property> <property name="minPoolSize">1</property> <property name="maxStatements">0</property> </user-overrides> </default-config> <!--name-config 自定义配置 需要声明name 如果c3p0DataSource调用xml自定义配置需要带name参数 --> <named-config name="intergalactoApp"> <property name="acquireIncrement">50</property> <property name="initialPoolSize">100</property> <property name="minPoolSize">50</property> <property name="maxPoolSize">1000</property> <!-- intergalactoApp adopts a different approach to configuring statement caching --> <property name="maxStatements">0</property> <property name="maxStatementsPerConnection">5</property> </named-config> </c3p0-config>
自动文件配置:
c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?> <!--c3p0根标签 --> <c3p0-config> <named-config name="wql"> <!--连接元数据信息--> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcurl">jdbc:mysql//localhost:3306/WQL></property> <property name="user">root</property> <property name="password">123</property> <!-- intergalactoApp adopts a different approach to configuring statement caching --> <property name="maxStatements">0</property> <property name="maxStatementsPerConnection">5</property> </named-config> </c3p0-config>
C3P0java文件:
public static void main(String[] args) throws SQLException { //指定数据名 ComboPooledDataSource pool =new ComboPooledDataSource("wql"); Connection conn=pool.getConnection(); System.out.print(conn); }
Comments | 1 条评论
博主 匿名
?
Warning: Undefined variable $return_smiles in /www/wwwroot/wql_luoqin_ltd/wp-content/themes/Sakura/functions.php on line 1109