📄 day04.txt
字号:
JDBC_day04 langna 2007-9-11 星期二
一、JDBC2.0扩展
1)DataSource:
数据库为了保证安全:用户名和密码经常换,并且很多时候我们根本就不知道用户名和密码;
每个客户端都要带着JdbcUtil ,分发重复,所以我们就想到了数据源
1、数据源是服务器产生和维护的;客户端只需去取就行;(不需要分发;不用每个点都去更新;)
2、客户端通过jndi服务器获得数据源的引用;
数据源是由服务器产生的,连接数据库用的,客户端和服务器往往不在一台机子上;
或不在一个虚拟机上;
将数据源放到公共区域中,(数据库不行)
2)JNDI
JNDI:java的命名和路径服务接口;
Java Naming and Directory Interface (JNDI) 的命名操作
JDBC和JNDI比较:
JDBC JNDI
接口集 接口集
驱动 服务提供者
物理存储(数据库) 文件系统、注册表、应用服务器等
JDBC 服务器:存储的数据海量的,有规则的,需要大规模检索;使用了SQL大规模的查询语言;
(集装箱)
JNDI 服务器:存的是个别的,种类繁多的,不需要大规模检索的;(储藏室)
存的都是java对象;
存:bind(name,object);
取:lookup(name);
基本功能、结构一样;
存的量和存的方法不同;
由于我们没有应用服务器;(tomcat等带有jndi服务器);
(1)造数据源对象,一般都是服务器产生的,我们不需要写;
(2)放到jndi服务器上,也不需要我们掌握;
(3)取数据源对象,需要我们掌握;
jndi的驱动就能把文件系统当成物理存储;加载驱动:(classpath)providerutil.jar/fscontext.jar
(1) 在服务器上造数据源对象
a. 连接jndi服务器:
在c盘中建一个jdbc文件夹;即提供jndi服务;
驱动的参数;
url:文件系统;file:c:/jdbc (file:/home/soft/jdbc)//创建一个jndi服务器
Context ctx=null;
ctx=new InitialContext(env);
b. 造一个数据源对象
OracleDataSource ods=new OracleDataSource();
ods.setDriverType("thin");
ods.setServerName("192.168.0.201");
ods.setNetworkProtocol("tcp");
ods.setPortNumber(1521);
ods.setDatabaseName("tarena");
ods.setUser("xjh0704");
ods.setPassword("xjh0704");
c. 将数据源对象存入jndi服务器
ctx.bind("oracle20",ods);
(2)写一个客户端:
a.连接jndi服务器
Hashtable env=new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
env.put(Context.PROVIDER_URL, "file:c:/jdbc");
ctx=new InitialContext(env);
b.获得数据源对象
DataSource ds=(DataSource)ctx.lookup("oracle20");
c.操作数据库
Connection con=ds.getConnection();
Statement st=con.createStatement();
ResultSet rs=st.executeQuery("select * from ln_student");
while(rs.next()) {
System.out.print(rs.getInt(1)+"\t");
System.out.print(rs.getString(2)+"\t");
System.out.print(rs.getString(3)+"\t");
System.out.println();
}
jndi就是放藏宝图的地方;而数据库就是宝藏,它肯定存在;需要藏宝图去访问它;
3)连接池:
事先把连接准备好,一般用数据源得到的连接都是池里的连接;
并在程序使用过之后不关闭连接,再放回连接池中等
待其他的程序在需要时来取用,这样可以大量的节省销毁和创建连接的资源消耗。
4)分布式事务:
a数据库:T1 提交 ,--> 转帐 --> b数据库:T2回滚;没有办法控制
将T1和T2合起来作为一个事务;
必须有第三方;weblogic,websphere 等应用服务器;
T1交给应用服务器,T2也交给应用服务器,每一个监控都有资源管理器;
所有资源管理器都让提交才能提交;
分布式的事务都是通过声明的配置进行的;
针对多个不同数据库同时操作,要保证原子操作的不可分割,
也不用再自己写commit,和rollback,全部都交给中间服务器来处理。
(两阶段提交),也就是在中间服务器发送sql语句等待数据库回应,
都回应操作成功才提交,否则同时回滚。
除非特别大的公司,一般不用分布式事务;
5)RowSet:行集
桌面上做快速开发的组件;将Connection,ResultSet,Statement集于一身;
是一个JavaBean的机制;
(1)综合对象
(2)JavaBean的结构,可以有图形界面、事件机制、序列化;
自带缓冲区,可以在网络上传递
缺点:
不够灵活
行集不属于jdbc的主流技术,ojdbc14 没有它的实现类;
提供一个jar包:rowset.jar
CachedRowSetImpl crs=null;
try{
//1.注册驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
//2. 建立数据库连接并执行sql语句
crs = new CachedRowSetImpl();
crs.setUrl("jdbc:oracle:thin:@192.168.0.201:1521:tarena");
crs.setUsername("xjh0704");
crs.setPassword("xjh0704");
crs.setCommand("select * from ln_student");
crs.execute();
//3.更新操作
crs.moveToInsertRow();
crs.updateInt("id", 99988878);
crs.updateString("name", "tony");
crs.insertRow();
crs.moveToCurrentRow();
crs.acceptChanges();
//4. 处理结果集
JdbcUtil.printRs(crs);
crs.first();
System.out.println(
"=============== crs.first() ===============");
JdbcUtil.printRs(crs);
}catch(Exception e){ e.printStackTrace();}
finally{
JdbcUtil.close(crs);
}
}
二、面向对象的数据库设计
对象ID:Accout a1,a2 ;
对象唯一性:变成记录存到数据库中,然后读出来时也要保证唯一;
对象在内存中天然的是唯一的,根据内存地址来区分;
但是存内存地址又是无意义的;java中不能存,即使用c++能存,但是这块内存是要被释放掉的;
再放对象的话,有可能构成重复;
内存中的对象放到数据库中要保证OID:
1)不重复;
2)足够使用;
分配OID的计数器必须是公用的,并且不能重复;
Oracle 中用sequence;或维护一个一行一列的表;并发时;但是性能上潜在不太好;
1、数学中的高低位算法:HighLow算法
对于一个应用程序:只读一次 :高位;
在数据库存一个公共计数器:
表里存的是高位:1 2 3 ... ;
在本机配一个私有计数器:
应用程序1)配一个低位值10001给一个对象,再来一个对象10002...
应用程序2)配一个低位值20001给一个对象,再来一个对象20002...
中国086-
北京:010-
广州:020-
上海:021-
2、 类应当对应到表,属性对应字段,对象对应记录。
类之间的关系对应表之间的关系或对应表;
继承关系:父类子类;
关联关系:有方向的;
OID作主键;
对于一个引用对象,存到另外一张表里;
(1) 继承关系的表建立:
1)每个类建一个表,为父子类每个类都对应的创建表,这种方法类关系清晰,
但是如果类比较多就不适合了;
父类的OID为外键,子类引用父类的OID,存一个子类的对象会存两个表的两条记录;
体现继承关系;
特点:
最接近于面向对象的结构;
查询效率低,任何一个查询都要连接表;不利于做报表;
在类比较多的情况下用这个;
2)所有类对应一张表,这种方法是在表中加上一个Type字段来区分父子类,
但是只能用于类属性较少的情况下,而且数据会有冗余。
特点:
结构简单,就一个表,查询效率高,做报表也很方便;
表太大,不太好维护,做索引不好做;子类的字段可以为空的;
这种用法还是比较多的;
3)只有具体类才建表,也就是把父类中的属性均匀分配到子类的表中,
也就是父类不建表,这种表关系不能使用多态;所有的父类字段都出现在
子类的表中,定义冗余;
特点:
查询效率也不是很高;
对多态支持不好;
优点不太突出,用的很少;
(2) 关联关系的表的建立:
一对一:汽车和发动机;看类之间引用的数目;
一对多:订单中有多个订单项的引用;
(维护一个订单项的集合)1:m(维护一个订单的引用)
多对多:客户和地址;m:m
通过中间表来维护;
中间表引用两表的主键当作联合主键,就可以实现多对多关联
三、类型转换查API即可;
四、程序设计:
1、程序分层
(1)什么叫分层?几种分层的方法?
两种分层的方法:
1)纵向分层:J2EE/JavaEE 按功能划分:
web层: 图形界面,跟用户做I/O的;
技术:Servlet,JSP(JSF/Ajax),Struts
业务层: 业务处理、计算;
POJO(JavaBean),EJB,Spring
持久层: OR/Mapping;对象关系之间的转化;跟数据库打交道
JDBC,Hibernate
2)横向划分:按抽象程度划分;
JDBC:接口集(抽象层)--驱动(实现层)
web:实现层 5
业务:抽象层 1
实现层 3
持久:抽象层 2
实现层 4
业务层的抽象-->持久层的抽象-->业务层的实现-->持久层的实现--> 画界面(web)
(2)为什么要分层:
1) 使得程序符合设计原则;
因为设计原则来源于实践和需求 ;
开闭原则:对扩展开放,对修改关闭;
依赖于抽象:不依赖于具体,减少耦合性;
组件和组件之间抽象耦合:
web层调用业务层的接口;
业务层调用持久性的接口;
2) 物理原因:web服务器和应用服务器和数据库服务器不在同一个地方;
3) 便于维护;便于扩展;便于交付使用;
设计:15%
开发:15%
测试:10%
维护:60%
以后的课程慢慢去体会;
补充:
CallableStatement cs=con.prepareCall("{call ln_pro_test(?)}");//调存储过程, p_test为存储过程的名字;
1) 存储过程是预编译的;
2) 为了安全;在代码中不能出现sql;从外部访问数据库没法访问;只能用存储过程;
可以写到sql文件里 ln.sql:
create or replace procedure ln_pro_test(i in number)as
begin
insert into ln_student values(i,'langna','shanghai');
end;
@ln.sql;/
存储过程相当于sql 语句,可以当脚本执行;
con=JdbcUtil.getConnection();
cs=con.prepareCall("{call ln_pro_test(?)}");
cs.setInt(1,14);
cs.execute();
五、分析项目:
1、定义业务接口,AccountService: 存,取,转帐
2、定义持久层接口,AccountDao:存,取,转帐
转帐没有更新数据;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -