数据库url:
jdbc(总协议):oracle:thin(子协议)@(分符)ip:1521(ip地址:端口号):sid(资源名称,数据库名)
可以和网络url相比较者看,东西不会多也不会少。
oracle url jdbc:oracle:thin://ip:1521:sid
mysql url jdbc:mysql://ip:3306/sid
编程环境
先要个驱动给一个oracle的叫ojdbc14这就是实现者。
驱动程序名字,oracle.jdbc.driver.OracleDriver这是个类名
1,Class.forName(),把驱动的类加载在jvm里面
2,new一个driver对象,然后调用DriverManager的registerDriver()方法;
两个的不同,一个是用字符串,一个是用构造方法,前一个的可变性更好。
3,可以用过命令行来切换不同的数据库,更加灵活。
java -Djdbc.drivers=驱动全名类名,在eclipse里面我们在,jvm参数传进来。
几个常用的数据库驱动的类名
驱动的名字最好还是在它的手册上查。
建立连接,实际上是调用了Driver的Connection方法,如果这个协议,驱动是不认识的就返回一个空,如果驱动认识就返回给DriverManager一个连接。
DirverManager不知道怎么联数据库,它会把协议交给在驱动列表里的类,DriverManager找第一个驱动,如果不是就返回null那就找下一个。知道找到或者到了最后。
1,n个,一个合适返回con
2,n个,都不合适no suitable driver
3,n个,一个合适,连接失败,返回sqlException
4,n个都可以用,用第一个。
excute(可以写更新或查询);它返回的是一个boolean类型的,
查询的话返回true,返回false执行的其他操作。都到statement里拿数据。
excuteUpdate();返回的整数是,这次操作所影响到的记录条数。
作业重复的部分写在一个工具类里面。写完了以后代码量很小。
6步3方法DriverManager的工作原理CreateStatement可以使用三个方法。
处理结果集next()getXXX()方法java的类型
关闭数据库有个顺序的问题。Statement和ResultSet都是有连接的,所以关闭顺序应该是打开顺序的逆顺序。一个Connection可以有很多个连接。
PreparedStatement
Statement
1,对字段内容表达不清楚。存入的时候
我们作了一个字接口。
PrepardStatement通过应用程序发一个代参数的sql给数据库。
insert into t_xxx values(?,?,?)
然后由preparedStatement在送一组参数值过去。
我有一万组参数就送一万次。
编译了一次运行一万次
参数类型明确了,准备参数值,
ps.setInt(1,8);
ps.setString(2,'hello');
ps.setDate(3,'dd-mm-yy');
这样是编译器介入检查了我们的参数类型。
PreparedStatement ps=connection.prepareStatement(sqlString);
Prepared准备
“select * from t_user where id=?”;
这一个占位符是用编号来代表的,ps.setString(1,"123");
执行后缓存在prepared里,因为参数不一定只有一个。所以
要调用ps.executeQuery();这里是没有字符串的。
1,创建PreparedStatement对象同时提供代参数的sql,会预先被数据库编译、
2,准备一组参数,缓存在PreparedStatement的内部。
3,通过某一个execute方法,把参数传给数据库,得到返回值。
如果还有要传的参数就重复2,3步。
ps的sql必须写在con。prepareStatement(“sql”)
关一个对象不是把对象清除,而是关闭一些改对象使用的资源。
元数据
数据类型本身的类型
ResultSet描述结果集的数据就是元数据。
字段的个数、类型、名称都叫元数据,
结果集元数据是用来描述结果集的数据。
ResultSetMetaData是对元数据进行操作的接口,可以实现很多高级功能。Hibernate运行
数据库的操作,大部分都是通过此接口。可以认为,此接口是SQL查询语言的一种反射机
制。ResultSetMetaData接口可以通过数组的形式,遍历数据库的各个字段的属性,对于开发者来说,意义重大。
JDBC通过元数据(MetaData)来获得具体的表的相关信息,例如,可以查询数据库中有哪
些表,表有哪些字段,以及字段的属性等。MetaData中通过一系列getXXX将这些信息返
回给我们。
MetaData包括:
l数据库元数据Database MetaData:使用connection.getMetaData()获得,包含了关于数据库整体元数据信息。
l结果集元数据Result Set MetaData
使用resultSet.getMetaData()获得,比较重要的是获得表的列名、列数等信息。
结果集元数据对象:ResultSetMetaData meta = rs.getMetaData();
字段个数:meta.getColomnCount();
字段名字:meta.getColumnName();
字段JDBC类型:meta.getColumnType();
字段数据库类型:meta.getColumnTypeName();
数据库元数据对象:DatabaseMetaDatadbmd = con.getMetaData();
数据库名=dbmd.getDatabaseProductName();
数据库版本号=dbmd.getDatabaseProductVersion();
数据库驱动名=dbmd.getDriverName();
数据库驱动版本号=dbmd.getDriverVersion();
数据库Url=dbmd.getURL();
该连接的登陆名=dbmd.getUserName();
事务
插入操作,只有两种可能成功和操作.
一个操作不能够再细分,并且结果只有成功和失败两种,这个操作就叫做原子操作.
原子操作的特征(很重要):要么成功要么失败.
事务是具备以下特征(ACID)的工作单元:
原子性(Atomicity)——如果因故障而中断,则所有结果均被撤消;
一致性(Consistency)——事务的结果保留不变;
孤立性(Isolation)——中间状态对其它事务是不可见的;
持久性(Durability)——已完成的事务结果上持久的。
原子操作,也就是不可分割的操作,必须一起成功一起失败。如果由insert和updata他们两条语句是成功还是失败,把这两个操作看作一整体.
它内部可以细分为两个操作,而且结果并不是简单的成功和失败两种.
原子操作,比较简单,容易控制,非原子操作,比较复杂,不容易控制.
原子操作的结果简单性,并不光是为了简单编码,而是这种结果简单性是必须的.
但有时我们希望把多个操作,变成以个原子操作,要成功都成功,要失败都失败.
事务就是把若干数据库操作,放在一起,看作一个整体,变成一个原子操作.
事务是一个边界.
买饼干,要么全买走要么一个都别买.
再商业中很多时候都是把操作分开规避风险.
而但对于审核等事情,都是以原子操作来表现的.
数据库状态的监控不容易把握.jdbc去监控数据库的话很不方便.
事务,原来数据的保存,数据库状态的监控,数据的恢复.
所以事务的实现就交给了数据库厂商.对他们来说比较容易.
数据的保存,本来数据库服务器就有日志.
数据库状态的监控,
数据的恢复
在jdbc代码上就是向数据库申请事务.
代码实现
1,关闭自动提交.jdbc针对单条操作,默认会在执行后就提交.
con.setAutoCommit(false);
2,进行正常的数据库操作,但并不会提交.
3,当所有操作完成,可以进行提交,con.commit();,不希望提交con.rollback();
如果在的2步中有一条操作出现错误,所有操作自动回滚.
如果都成功了那么就进入到第3步.如果提交就变成永久数据.
在没有commit之前所有数据都是临时数据.
原子操作完成应当把自动事务提交打开con.setAutoCommit(true);
注意,第3步一定要做,如果程序结束,数据库有可能会提交,不同数据库不同操作.
但如果程序非正常结束……
事务性资源,数据库就是一个事务性资源,可以兼顾到数据完整性.
企业应用里很需要这种资源.
事务在数据库里执行的时候,并不是独占式的执行.
事务还有个并发控制问题,事务也是在以个时间段里完成,而且表也是单一资源,
那么会有多个事务在同一个时间操作同一事务,产生并发问题.
事务的并发,在数据库的实现里是一个课题,对程序员也有一定的影响.
并发控制并不是只使用单一的手段.必须要知道产生并发对我们的影响清楚.
逻辑,1研究并发会产生那些不同的后果,2,根据这个后果我们要采取那些手段.
三种错误
1,Dirty Read脏读,读到了未提交数据;
一个事务在运行期间读到了另一个事务没有提交的数据.
现在有两个事务都在被银行账户上操作,一个给账户存钱,另一个也给账户存钱.
严重程度:严重的错误.数据的准确和完整受到了损害和,
2,Unrepeatable Read不可重复读,
也会引起不好的结果,一个事务读到了另一个事务提交的数据.在一个事务里面前后读两次但两次数据步一致,就是步可重复读.
这个是正确的结果,但是在某些特定的情况下就不可以了.
列:一个银行账户,地址是南京,A事务要改北京,B事务要改西安;整体逻辑是要南京改西安,但是在A事务提交后,B要南京改西安,可是现在读到是北京不是南京,如果不考虑原始数据事务也提交了,最后更新丢失.和整体逻辑不相符.
3,phanten Read幻读
前后两次读到的数据量上发生了变化.
A事务第一次读到两条记录,第二次读到三条数据.这两次读到的数据都是对的,只是有另一个事务提交的数据.
数据的稳定性有一定的影响.
对这三种错误,我们生成了五种控制.
大多数据库都不允许脏读.这种控制级别一般都是默认的.
五种级别是由数据库服务器来做的.
1,TRANSACTION_NONE无事务
2,TRANSACTION_READ_UNCOMMITTED读未提交的数据(理论上一说)
3,TRANSACTION_READ_COMMITTED只能防止脏读(这条是默认的,不设置也有)
4,TRANSACTION_REPEATABLE_READ防止脏读和不可重复读.
5,TRANSACTION_SERIALIZABLE事务串行化,实际就是取消了事务并发,效率受到损失.
串行化会引起效率下降,一般情况下对我们代码没有影响.
这几个常量是在Connection类里面定义的,一定要在连接打开之后就去设置.
connection.setTransactionlsolation()
JDBC2.0
这个和java没有什么关系,虽然这个版本升的很快,但改变并不大.
主要是在几个数据结构上发生了一些变化
第一方面主要是增加了,ResultSet功能上的增强,Statement功能上有所增强
加入几个数据结构.
1,可滚动
2,可更新
在设置结果集的时候,结果集读一回就不能读了.
在企业的应用来说,一般是把结果集的数据读出,变成对象然后来处理对象.
现在这特性在一次性结果集的增强.
滚动性有两层意思,
1,游标不光可以向后移动,还可以向前移动.
2,游标可以相对移动也可以绝对移动.
可更新的意义
可以在结果集里修改数据,直接反映到数据库里面.
他们都用在小的桌面应用里面
得到这两种特性:
要告诉数据库我们需要一个可滚动的结果集,通过常量得到
TYPE_FORWARD_ONLY就是单向的结果集,这个常量是理论上的意义
TYPE_SCROLL_INSENSITIVE非敏感可滚动的结果集
TYPE_SCROLL_SENSITIVE敏感可滚动的结果集
敏感:数据库中的数据发生变化后,是否能反应在结果集里.
这一点还要看数据库的驱动是否支持.
因为结果集在2.0里面不光增加了滚动特性,还有更新特性.
就是在要结果集的时候这两个东西都要指定才能得到
CONCUR_READ_ONLY只读
CONCUR_UPDATABLE可更新
FETCH是读的意思,fetch data就是抓去数据
FETCH_FORWARD游标的方向是正方向,从记录的小编号到大编号
FETCH_REVERSE游标的方向是反方向,
FETCH_UNKNOWN不知道游标现在的方向.
Statement stmt=con.createStatement(resultSetType,int resultSetConcurrency);
//时机在创建statement的时候就确定要什么结果集.
//不是在查结果集的时候要,那个时候就晚了.
//以前是没有参数的,现在有两个参数,
//第一个指定结果集可滚动特性,第二个指定结果集可更新特性
//现在大部分驱动都支持滚动特性,还有一部分不支持可更新特性
//注:只有在必要的时候(如桌面应用)才用结果集更新数据库,因为使
用结果集更新数据库效率低下。可更新结果集还要看数据库驱动程
序是否支持,如Oracle就支持MySql不支持。并且只能针对一张表
做结果集更新。而且不能有join操作。必须有主健,必须把非空没
有默认值的字段查出。处理可更新结果级时不能用select *来执行查
询语句,必须指出具体要查询的字段。
Positioning定位方法,下面是可滚动结果集可以用方法,
这里的方法都是游标定位方法.之前的结果集只有一个定位方法next();
这些方法都是体现上面四点.
boolean absolute(int row);
绝对定位,row是记录编号的意思.
定位成功返回true,游标移到指定位置.
定位失败返回false,游标不移动
void afterLast(),
定位到最后一条记录的后面,即使结果集里面没有记录也有这条记录
void beforeFirst()
定位到第一条记录的前面
boolean first()
boolean last()
定位到第一条或最后一条,从逻辑上说这是相对定位.
他们不能保证存在.
boolean next()
从当前记录开始向下一条
boolean previous(),
从大的记录号到小的记录号
boolean relative(int)
相对定位,参数可以是正整数也可以是负整数
正数和next()一个方向
负数和previous()一个方向
下面是判位函数
boolean isAfterLast(),是否在最后一条的后面
boolean isBeforFirst(),是否在第一条的前面
boolean isFirst(),是否在第一条
boolean isLast(),是否在最后一条.
con.createStatement(ReusltSet.TYPE_SCROLL_INSENSITIVE,
ResuleSet.CONCUR_UPDATABLE)
可更新特性的使用
rs.updateXXX(字段,值);
1,把游标移动到要更新的记录
2,更新这一行上的记录值
3,执行一个rs.updataRow();
删除
1,把游标移动到要删除的记录rs.absolute(10);
2,执行rs.deleteRow();
插入操作
1,moveToInsertRow();
移动到要插入的行.插入行是一个缓冲区,
这个缓冲区的结构和结果集一样.
第一件事情把当前记录记下来,然后再把游标移动到缓冲区.
2,rs.updateXXX(字段,值)
把数据写入缓冲区
3,rs.insertRow();
把缓冲区的数据加入结果集,结果集无顺序,
同时也会更新到数据库
缓冲区清空
4,rs.moveToCurrentRow();
把游标移动回移走之前的位置.
可更新性的使用的条件.
驱动.
可更新结果集不可以随便获取,他是通过部分的数据更新数据库
结果集的结构和表的结构不一定是一样,
要满足条件才可用
1,查询只包含一张表
2,不能使用join操作
3,要把主键查询回来.
4,非空的字段都要查询回来和有默认值的.
批处理
只有更新有批处理,insert,delete,update
ps的意思是什么呢,数据库就给它编译了.
一组一组的送参数,一次只送一组参数.
再数据库和数据之间的网络连接,
在做数据传输的时候网络的效率严重的影响系统应用的效率.
送盒饭100人,送100盒,如果一盒一盒送每盒来回5分钟,如果一次100盒,我们这有并发的处理这100盒饭的能力.
如果你一次一组数据,数据库只用一个线程来处理.
如果你一次50组数据,数据库就可以多开几个线程来处理.
语法Statement
Statement stmt=con.createStatement();
stmt.addBatch("insert into t_user");加入批量处理.
有多少个异构的sql就用上面的方法加入Batch.
最后int[] results = stmt.excuteBatch();
但是这个里面的sql只能写更新,不能写查询
1,addBatch()
2,executeBatch()
语法PreparedStatement
PreparedStatement ps=con.prepareStatement();
ps.setXXX();
ps.addBatch();这个是把这组set里的参数放到Batch里面去.
然后再准备参数进行addBatch();
你加了多少sql或参数Batch的size是多大
int[] counts=ps.excuteBatch();
一般是把数据的组放在20到50个之间.实际情况是一批如果太大那就慢了
sql99 -> sql3里面有几个类型被jdbc2.0采纳
采纳的有
数组
数据库种建立数组的语法
create type数组名as varray(10) of number(4);
oracle建立一个名字类数据名长度为10类型为number的数组
create table
牵扯到数组的会有个可移植性的问题
读到数组的东西,第一次读到的数组时jdbc的数组,需要继续getArray()
Array vs=rs.getArray();
BigDecimal[] values=
STRUCT
结构里面的一个distinct它是个别名
create type money as numberic(10,2);money就是numberic(10,2)类型的别名.
主要的用途是,如果有很多表都用到这个类型,当需要修改精度的时候,需要怎么做.
numberic时个范围很大的数.把这个范围限制之后起个名字叫money;
create table XXX(salarynumberic(10,2));
用处,在很多表都有这numberic的使用,如果没有这个别名,那这些地方都需要手工去改.
然而现在有了别名我们就只需要改这个别名建立的地方.
BLOB
独立类型
处理特大对象
以前的大字段有个大小的上限,例如longvarchar 200M,还有这个大字段可以在数据库管理上调,但是他的大小还是固定的.
在blob和clob之前都是一次性读取.
一次性读取,就是一次性的读走全部内容.
如果想把所有记录都读到,1000条记录*1M,那么结果集就要存1个G的内容,这是不可接受的.
1,大小有上限,2,读取需要一次性读.
这是两个大对象字段,lob->large object b-> binary c->character
字符和二进制的语法是一样,处理的资料的存储方式不同.
从种类上说二进制的文件种类多.字符的以文本文件为主.
blob能存的东西很多.
怎么写blob
把二进制文件的内容写到数据库里面去.
虚构了一个表,建立以个空的blob对象结果集
create table t_blob(
id number(10) primary key,
filename varchar(20),
blob_data blob);
现在已经有了一个空的blob,如果要想执行写blob,
ps=con.prepareStatement("insert into t_blob values(?,?,empty_blob()");
ps.setInt(1,1000);
ps.setString(2,file);
ps.ecuteUpdate();
//1.先存一个空的blob
ps=con.prepareStatement("select blob_data from t_blob where id=? for update")
for update的意思是给这个字段加了以个读锁,并且表示读过来之后可以对它修改.
ps.setInt(1,1000);
rs=ps.executeQuery();
rs.next();
blob=rs.getBlob(1);
//3.把文件中的内容写到blob对象中.
InputStream fin=new FileInputStream(file);
OutputStream out=blob.setBinaryStream(0);
long avaibale=fin.available();
byte[] content=new byte[available];
fin.read(content);
out.write(content);
fin.close();
out.close();
//4.把已经有数据的对象blob对象存入数据库
ps=prepareStatement("update t_blob set blob_date=? where id=?");
ps.setBlob(1,blob);ps.setInt(1,1000);
ps.executeUpdate();
con.commit();
怎么读blob
ReadBlob
blob可以用流式读取,读的时候只读一个引用过来.
然后我打开一个流,那么我可以一点一点的读,这都是采用流式的方式.
流媒体播放器,一点一点的读取,
怎么去读这个字段,
Blob blob=null;
ps=con.prepareStatement("select blob_data from t_blob where id=?");
ps.setInt(1,1000);
ps.executeQuery();
rs.next();
blob=rs.getBolb();
//2写入一个本地文件
OutputStream fout=new FileOutputStream(args[0]);
InputStream in=blob.getBinaryStream();
//blob打开的输入流,不能用available(),因为它得不到正确的长度.blob在远程数据库里
byte b=0;
int i=0;
while(b=in.read()!=-1){
fout.write(b);
if(i%1024==0){
System.out.println("read .... "+i/1024);
}
}
in.close();
fout.close();
CLOB
字符大对象
用法和BLOB一样的
数据源和jndi
连接池和分布式事务
RowSet新的接口,日后说不好会有应用.
数据源
jdbc里面用到jndi的部分主要式使用数据源
在连接数据库的时候,需要url用户名密码,这些东西都是保密的,并且也经常会改.我们不能老去更新密码.数据库连接信息进行封装的东西就是数据源
数据源有连接数据库的能力,他不会返回任何连接信息。
一般是服务器管理员来造的数据源.然后给我们应用程序员来使用.
数据源在服务器里,应用程序员在应用服务器里.这两个东西不在同一个进程里.
那么数据源的传递也是一个问题.必须想一个办法让客户端自己来取.
但是如果把数据源放到应用服务器上,那么又成悖论了.
那么数据源就放在JNDI这个公共的服务器上,这是个公共区域.
公共区域大家都可以访问到的区域
JDNI就是大家都可以方便的访问到的东西.
JNDI和jdbc的api是平行的.
j2se->jdbc
j2ee->jndi
借助jdbc来理解jndi
1,数据库是存数据的,jndi也是存数据的,并且他们的数据都是公共的.
2,jdbc和jndi都是一堆接口.
jdbc->jdbc有驱动->DB物理存储
jndi->jndi也有驱动叫服务提供者->loap(目录),文件,甚至注册表,包括数据库,等物理存储
1,数据库存的数据是有规则的海量数据.而且是二维表结构
2,jndi里存的是无规则的小型少量数据.
jdbc有关系的数据,量大,规则.有很高的数据基础,sql作为访问接口
jndi适合非关系,量小,都是离散的数据,访问接口非常简单.
仓库,任何东西都在10分钟就能找出来,看他摆放不是乱摆.
小屋,里面什么都有,什么数据都在里面
有规则的海量的数据,可以通过有数学基础的查询语言来进行存取
不规测的小量的数据,可以通过简单的查询语言来进行存取.
数据源创建
存ds->jndi.bind("x",ds);
取(DataSource)jndi.lookup("x");
jndi服务器都在应用服务器里面,
操作数据源
把数据源存入jndi服务器
1,create ds
2,连接JNDI服务器,得到一个连接对象jndi
3,jndi.bind("x",ds);//把数据源存入
连接jndi,取出数据源得到数据库连接.
1,连JNDI SERVER
2,ds=(DataSource)jndi.lookup("x");//在服务器找数据源
3.Connection con=ds.getConnection();
数据源大部分情况下是通过配置得到的数据源对象.
这项工作回由应用服务器来管理的.
要找到oracle的数据源的实现类找出来,然后再把里面的相应的参数设置好.
这个完了以后才是重要的.
连jndi的语法,在课件的p97
Context代表jndi的实现类,代表jndi服务器
initialContext Context的实现类.
jndi只要new这个实现类就可以了,这个类再jdk里面就由.
最后把它bind到服务器里面.
先要搭建一个jndi的环境
jdk->文件系统的服务提供者->文件系统
服务提供者的两个jar包,
providerutil.jar服务提供工具
fscontext.jar文件系统上下文
main方法里面
连接jndi服务器,
造一个数据源,OracleDataSource ods=new OracleDataSource();//在ojdbc14.jar包jdbc pool
然后要设置用户名,密码,服务器名(ip),DriverType('thin')
创建一个集合hashTable,用来存放参数
put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.fscontext.RefFSContextFactory")//相当于jdbc里的驱动
put(Context.PROVIDER_URL,"file:c:/jdbc")//相当于jdbc的url
然后ctx=new InitialContext(env);
bind(ctx,"jdbc/oracle26")//把连接对象传到自己写的一个函数里面
以上步骤,连接到了文件系统的服务器.
1,准备参数
2,连接
文件系统本身就是个服务器,文件系统做服务器是不奇怪的.
名字也就传进来了.
下一步,把数据源通过一个名字存入jndi服务器里面
ctx.bind(in,ods);
这样就把数据源存起来了.
1,造一个数据源
2,连接jndi服务器.这步比较复杂.要设置的参数不大一样.
3,把数据源存入jndi服务器
后面的工作才是我们做的,数据源查的工作
1,连jndi服务器
2,lookup(数据源名),查出来的是个Object,转成DataSource这就是jdbc的接口了
3,ds.getConnection()得到数据库连接.
大家把两个包放到编译环境里面才有用
连接池
也是在后台使用的,在我们自己的代码里面一般体现不出来
通过数据源得到的连接,基本上都是池里的连接.
在语法上不会对代码由什么影响,
连接池,就是说,连接放到缓冲池里面,如果用的话,就分配给你一个,如果用完了就把连接还给连接池.所以在连接池里面就存在一个调度的算法,
应用服务器有的也提供连接池的应用.
连接池一般也是由管理员来配.
分布式的事务
java的分布式事务的API叫JTA
转帐的操作讲事务的时候已经说过了
取款和存款的操作不在一个服务器内部.
一个服务器监控一个事务,而另一个服务器也监控一个事务
现在要这两个事务成为一个事务
这就需要分布式事务,这就需要事务在多个节点.
数据库A数据库B他们只能自己管自己的.要管理这个事务就要第三方来管理
RowSet
叫做行集
它不属于传统的jdbc的内容,传统的jdbc所有的东西分的比较细
rowSet比较粗,针对桌面程序的快速开发,
1它合并了connection statement resultSet
行集可以发展为控件,有这个能力很容易能够看的见
3它可以离线操作.如果没有数据库连接ResultSet依然可以用
4还有它天生可滚动可更新
RowSet语法
只是接口没有实现类,也需要一个rowset.jar
用的就是com.sun.rowset.CachedRowSetImpl,又指望各大数据库厂商实现
很多驱动还没有支持RowSet,这个技术还是比较新
RowSet还是jdbc内部的接口
jdbc的接口都需要驱动,RowSet这个包就好像给驱动打了一个补丁
RowSet不能替代驱动也不能替代驱动这个包.所以还必须又这个包
简单的语法
两种用法:
cachedRowSet不能存放太大的结果集.
添到这个rowset里面又什么意义呢,把结果集填充到rowset里面的重要原因之二.
1.离线
2.可更新,可滚动
rowset可以替代ResultSet,因为rowset继承了ResultSet接口.
beforeFirst也行
ooad与数据库结构
Id通常是用来表示记录的唯一性的,通常会使用业务无关的数字类型
Object id对象的id,sequence只有Oracle才可用,对象id(OID)使用高低位算法先生成高位,在生成低位,通过运算获得对象id。
类应当对应到表,属性对应字段,对象对应记录。
类继承关系对应表,
1,每个类建一个表,为父子类每个类都对应的创建表,这种方法类关系清晰,但是如果类比较多就不适合了
2,只有具体类才建表,也就是把父类中的属性均匀分配到子类的表中,也就是父类不建表,这种表关系不能使用多态
3,所有类对应一张表,这种方法是在标中加上一个字段来区分父子类,但是只能用于类属性较少的情况下,而且数据会有冗余。
类关联关系对应表
1,一对一关联,类关系对应成表时有两种做法,一是引用主键,也就是一方引用另一方的主键既作为外键有作为自身的主键。二是外键引用,一方引用另一方的主键作为自身的外键,并且自己拥有主键。
2,一对多关联,也就是多端引用一端的主键当作外键,多端自身拥有主键。
3,多对多关系,多对多关系是通过中间表来实现的,中间表引用两表的主键当作联合主键,就可以实现多对多关联。
三个概念
jndi
数据库连接池
分布式事务vaBean的定义:
1、是一个普通的Java类
2、在结构上没有预先的规定,不需要容器,不需要继承类或实现接口
3、要求必须放在包中,要求实现Serializable接口
4、要求有一个无参的构造方法.
5、属性的类型必须保持唯一,返回值必须和set方法参数类型一致
6、对每个属性要有对应的get和set方法。注:隐藏属性可以没有
7、可以有外观作为显示控制,事件机制。