(6)JDBC个人理解

JDBC

java DataBase Connectivity 用于连接java和数据库,是sun公司推出的一套java应用程序访问数据库的技术规范
规范:抽象类和接口
从java存取数据库的技术有JDBC,JDO(java data object封装了JDBC),框架(Hibernate,Mybatis,封装了JDBC)
是独立于数据库管理软件的,定义了一套接口来实现java与数据库,通用于mysql,oracle,SQLserver,DB2,这样可以提高可移植性
MVC是一种设计模式
M(model),封装应用程序的数据结构和事务逻辑,是应用程序的状态,当状态改变时,能在视图中体现出来,可以由Javabean来体现,包括Dao(数据访问层,用来与数据库连接),实体bean(vo),业务逻辑层(Service)
V(view),是model的外在表现,由JSP来体现
C(controller),对用户的输入进行响应,将模型与视图结合到一起,可以将数据写入模型,并调用视图,可以有servlet或者spring的controller来体现
三层架构是表现层(用户界面view),业务逻辑层(对数据进行逻辑处理Service,没有输入输出就是实现功能),数据访问对象层(针对数据库的操作与交互DAO data access object 增删改查操作),他们都会用到模型层domain(业务实体类,javaBean)这是典型的上下关系,上层依赖下层,但MVC是没有上下关系的,而是互相协作关系,其实算表现层的分解。访问的时候是从表现层到业务层再到数据访问对象层,但写的时候是先写业务实体类,再写DAO层,再写业务逻辑层,最后写表现层。
内容总结
主要就是两部分内容,第一步连接数据库,第二步执行操作。第一步得到的结果是Connection c,第二步利用c来获得preparedStatement,然后用s来执行修改语句或者是查询得到结果集r,最后关闭连接。
改进(简单封装)第一步是封装连接和关闭,参数放到properties中。第二步是封装执行的操作,分为增删改,查询单个,查询多个。
然后学习java中批处理的函数(其实就是改进了s执行的步骤),学习二进制数据如何插入。
然后分别针对连接和执行学习连接池和DBUtils来进行更方便的封装(官方封装
DAO层也就是运用了连接池和DButils的JDBC,其中有方法增删改(传的参数就是sql语句和占位符参数),查单个,查多个,查一个数据(这里虽然用的是DButils中的query,一个方法全搞定,传入c,参数,sql语句,还有ResultHand,而这个接口需要知道现在查的是什么才能实现对应的实现类。所以还是得分开,这里传的参数有sql语句,占位符参数Object… params,还有现在是什么类,也就是一个class文件,Class c)
Service中放的是利用DAO来提取数据,处理业务逻辑代码,比如说login方法,接收name和password,然后利用query去查询。在view层就是接收到密码和用户名,然后利用service层的方法去判断。

基础步骤

首先复制mysql-connected 的jar包到项目的根目录或者是libs中,然后build path – add to build path
要引用java.sql包中的一些类,还引用com.mysql.jdbc.Driver这种驱动包
1.加载驱动(将类加载到内存)
DriverManager.registerDriver(new Driver()); //这个driver就是外部引入的驱动包中的类,这一步是为了加载驱动类(这一步会需要在方法throws异常,也可以在内部throw,当然也可以try catch)
2.获取连接(把java当成客户端连接数据库)
Connection c=DriverMager.getConnection(“jdbc:mysql://localhost:3306/wsy”,“root”,“root”); 就是输入mysql -P -u -p等信息
3.执行操作
String sql=“sql命令”;
Statement s=c.createStatement(); //获取命令对象来执行sql语句
s.executeUpdate(sql)//处理语句,会返回一个int值,受影响行数,大于0为执行成功
4.关闭连接
s.close();
c.close();

改进1:将需要参数装入properties

可以创建一个properties文件,里面放user=xx password=root url=jdbc:mysql://localhost:3306/wsy driver=com.mysql.jdbc.Driver。
Properties p=new Properties();
info.load(new FileInputStream(“src\jdbc.properties”)); 这里路径就用文件在的路径
String user=p.getProperty(“user”);
String password=p.getProperty(“password”)
String url=p.getProperty(“url”)
String driver=p.getProperty(“driver”)
1.加载驱动(将类加载到内存)
driver就是外部引入的驱动包中的类,创建它的时候会执行一个静态代码块,在这个静态代码块中driver对象其实已经创建过一次了,如果在外面再创建一次,效率很低,而且根本没用过这个对象所以我们一般不用new对象来加载这个类,而利用反射
Class.forName(“com.mysql.jdbc.Driver”)而且这个是运行时加载,编译时即使不存在这个类也不会报编译错误(降低类依赖性);创建1遍,效率高
还可以用一个properties文件存放这个字符串class.forName(driver);
2.获取连接(把java当成客户端连接数据库)
这样把密码和用户都暴露出来了,可以传入DriverMager.getConnection(url,properties类型的对象)
最好还是创建一个properties对象,把值都存在里面,这样易于改变。
Connection c=DriverMager.getConnection(url,user,password);
3.执行操作
String sql=“sql命令”;
Statement s=c.createStatement(); //获取命令对象来执行sql语句
s.executeUpdate(sql)//处理语句,会返回一个int值,受影响行数,大于0为执行成功
ResultSet r=s.executeQuery(“select a from A where name=’”+name+"’")//会返回一个结果集用ResultSet对象去接收
r有一个next()方法,一开始在-1处的位置,执行一次下移一行,如果有值则返回true,无值返回false,等到了这一行再用方法来获取这一行的值,还有previous()可移动到上一行,并返回是否有值
到了这一行则取值getInt(1)方法就是返回1位置的数值 getString(2)返回2位置的字符串 getInt(“列名”)也可以通过字段名来返回值
当不知道类型的时候,最好用getObject
4.关闭连接
r.close();
s.close();
c.close();

改进2:使用PreparedeStatement(增删改查都可以用)

PreparedeStatement继承了Statement,是其的改进
因为用户输入数据,然后拼接到sql语句中,如果输入了一些非法的语句,那会导致运行出错,这种现象为sql注入,所以使用preparedStatement,
会由占位符来输入数据,在查询之前预处理,如果不能执行就直接不执行了,而不会报错导致程序异常终止
(1)不使用+来拼接sql,减少语法错误,语义性强
(2)将sql和参数进行分离,提高维护性
(3)解决sql注入
(4)减少编译次数(每次运行只编译了一遍sql)
String sql=“select a from A where name=?”;
preparedStatement s=c.prepareStatement(); //获取命令对象来执行sql语句
s.setString(1,name);//设置占位符的值
ResultSet r=s.executeQuery(sql)//会返回一个结果集用ResultSet对象去接收

改进3:简单的封装连接和关闭

因为增删改需要的注册驱动,获取连接还有取消连接和查询需要的其实大部分都差不多,可以利用一个工具类来将他们封装起来
可以弄个新的工具类JDBCutil,用方法getConnection()来获取连接 ,内容就是获取连接(properties的创建,还有加载驱动可以放在静态代码块中,类加载即可运行且只加载一次,变量在外面用static,当然这里没法throws,所以只能try catch,在catch里将异常抛出一个RuntimeExcetion即可,这样可以将编译异常转换为运行时异常
用close()来关闭,三个参数分别是resultSet,Statement,Connection(也可以重载三个方法),根据这个到底有没有来决定是否关闭这个参数。
注意这里用的是Statement而不是prepareStatement(即使一般用的都是pre),因为这样就不够通用,而Statement是父类,都可接收

改进4:简单的封装执行操作

1.增删改int update(String sql,Object…params)
在update里面就是获取连接(利用封装好的利用druid连接池的获取连接方法),然后获得statement,传参数(利用for循环,params.length,用params[i]来取值,记得设置参数时statement是从1开始的,所以要用i+1),执行sql语句,返回执行结果int值
2.查询querysingle(String sql,Object…params)
首先这里要明白返回的是什么,返回的应该是一个对应表的类对象(与表的字段相同的类也就是javaBean,要求字段名和类的属性名,类型的话要求java中使用包装类(因为引用数据类型才有null值,char用的也是String,因为mysql中char(1)其实是String)
在获取连接,获得statement后,赋值占位符参数。执行查询获得ResultSet,然后要将它的值封装到对应的类中。返回对应的类
这里针对的是单个类的查询,如果要查多张表,可以使用泛型
3.查询queryall(String sql,Object…params)
返回一个类的集合List,查询类似,这样只能查一张表,可以使用泛型来查多张表

批处理

在java中支持批处理,可以成批的更新或者插入记录,一次性拿多个数据给数据库比一次性处理一条更有效率,一般配合preparedStatement使用,既可以减少编译次数,也可以减少运行次数。(即所有操作都放preparedstatement,在用setxxx设置占位符的值之后,用addBatch添加到包中,在循环到某个自己设置的地方excutebatch,执行完后clearbatch,再开始下一次的设置占位符)
addBatch() 可以用来添加需要批量处理的SQL语句或者参数
excuteBatch()批量执行语句
clearBatch()清空批处理包
具体使用有两种方法
(1)没有规律的多条语句(意味着没法统一设置占位符) 使用Statement去处理,一条条的加s.addBatch(sql1) s.addBatch(sql2)
(2)第二种是同一条sql语句,只是参数不同,则可以使用preparedStatement 用c.prepareStatement(sql);得到s
然后循环 设置参数并加入batch中。 然后用s.excuteBatch(),执行完后clear
JDBC支持批处理的版本是mysql5.1.37 而且在url(就是获取连接c的时候传进的url)中还要加一个参数是?rewriteBatchedStatements=true来开启批处理
记得批处理时要插入要用values。
可以在用的时候比如插入50000条,可以每1000条处理一次

插入二进制数据图片

这其实就设置一种特殊类型的占位符,不是setString,不是setInt,而是setBlob
blob是一个二进制大对象,可以存储大量数据,可以容纳不同大小数据
setBlob(1,Blob b)或者传入流 setBlob(1,new FileInputStream(“路径”))
读取的时候sql就正常的,用select xxxx
获取到结果集set之后,Blob b=set.getBlob(“photo”)就可以得到一个blob对象 InputStream i=b.getBinaryStream()也可以直接得到一个流
或者是set就直接有方法是set.getBinaryStream(“photo”);
文件处理
怎么处理这个InputStream流呢,要用outstream流来将它输出到某个路径下,创建一个新的路径
FileOutputStream f=new FileOutStream(“xxxx”)记得用\ 这就是创建一个新的文件
int len;
byte[] b=new byte[1024];
while((len=i.read(b)!=-1)){ //只要读出来不是-1
f.write(b,0,len); 每次将b中的内容写入到文件f中
}
f.close();
i.close();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值