吉林大学数据库应用程序开发知识点总结

吉林大学数据库应用程序开发知识点总结

这是我在复习数据库应用程序开发的时候记录的笔记。我们这一年的考试题(2021级2023年12月31考试)共计两道题。第一题是根据实验报告出的,每道题基本上涉及一个知识点;第二题是对于吉祥码的分析题,也是以数据库为核心,操作为辅助的题目。整体难度不大,知识点都在下文提及。

知识点1 学习如何连接数据库

1.1 加载数据库驱动程序

Class.forName("COM.ibm.db2.jdbc.app.DB2DRIVER");

1.2 创建数据库的连接

String url = "jdbc:db2:samle";
String userid = "db2admin";
String passwd = "db2admin";
// 对数据库进行连接
Connection sample =
    DriverManager.getConnection(url,userid,passwd);

1.3 结果集ResultSet和Statement语句

对于完整的SQL语句(需要符合SQL语法)可以直接执行。

String sql = "SELECT * FROM JLU.EMPLOYEE WHERE EMPNO = 000010";
Statement stmt = sample.createStatement();
ResultSet res = stmt.executeQuery(sql); 

1.4 标签标记PreparedStatement语句

这个语句有缺省处理的效果。可以利用?在sql语句中制造缺省值,但是在执行前利用preparedstatement进行补充。

String sql = "SELECT * FROM JLU.EMPLOYEE WHERE EMPNO = ?";
PreparedStatement pstmt = sample.prepareStament(sql);
pstmt.setString(1,deptno);//带标签标记的deptno要在前面获取到
// 如果需要补充的是int类型
// pstmt.setInt(1,deptno);
// 有几个?就需要补充几个标记
// 标记的顺序和?相同
int row = pstmt.excuteUpdate();

1.5 将结果存储到结果集

while(rs.next())
{
	String data1 = rs.getStirng(1);
	String data2 = rs.getStirng(2);
	String data3 = rs.getStirng(3);
	/*
		从1开始获取数据
		函数里面的逻辑可以自己rewrite
	*/
}
  • rs.getString(n)读取String类型

  • rs.getInt(n)读取Int类型

1.6 关闭jdbc对象

  1. 关闭ResultSet
  2. 关闭PreparedStatement
  3. 关闭Connection
if(rs != null)
{
	try{
		rs.close();
	}catch(SQLException ee){
		ee.printStackTrace();
	}
}
if (pstmt != null)
{
	try{
		pstmt.close();
	}catch(SQLException ee){
		ee.printStackTrace();
	}
}
if (sample != null)
{
	try{
		sample.close();
	}catch(SQLException ee){
		ee.printStackTrace();
	}
}

注意:关闭jdbc链接并不代表已经提交了事务。

知识点2 GUI窗口交互

2.1 使用JOptionPane进行提示输入交互

  • 使用showMessageDialog进行消息提示
JOptionPane.showMessageDialog(null,"已经更新的数据"+emptno)
  • 使用showInputDailog进行输入对话,会将消息存储在input中
String input = JOptionPane.showInputDialog("请输入一个emptno\n");

2.2 使用JTable创建数据库表格

这个JTable我们给出的方法比较老了。

我看ChatGPT给出的方案是:先建立一个DefaultTableModel dataModel;将数据存储到这个model中,然后再将model添加到JTable中。每次刷新dataModle,不然每次添加数据再重新创建一个JTable效率太低,而且太占内存了。

String[][] lineNames = {"编号","名","中间名","姓"};
Object[][] line = new Object[4][4]; 
// 使用Obeject对象只是引用,并不占据内存
dataModel = new DefaultTableModel(data,lineNames);
Jtable jt = new JTable();
jt.setModel(dataModel); 

刷新的话,可以先更新line 数组里面的数据,然后

importData();
dataModel.setDataVector(line,lineNames); 
// 更新DataModel就好了

Excle应该就是用这种方法开发的。

2.3 获取JTable中的数据

String cellValue = (String) tableModel.getValueAt(row, column);

知识点3:插入,删除,修改操作

  • 单行插入
String sql_insert = "insert into templ (empno,firstname,midname,lastname)";
  • 多行插入
String sql_insert = "insert into templ(empno,firstname,midname,lastname)";
int count = num;// 用户想插入的行数
for (int i=0; i<count; i++)
{
    sql = sql +",(?,?,?,?)";
}
  • 通过子查询插入
String find_insert = "insert into templ(empno,firstname,midname,lasername)";
String select_query = "select * from JLU.emplyee where ? = ?";
String find_insert = find_insert + select_query;
  • 实现对结果集的任意行、任意列的修改

需要知道这个实现的思路就是先导入到物理存储上,然后对物理存储修改,再写入数据库。

这过程中有对锁思想的实现。(U锁的获取,老师的视频课里面讲解了)

实现方法 1:

String str = "";
String selectForUpdate = "select * from employee for update";
// 注意 for update语句。这条语句作为sql是不符合规则的,但是jdbc会知道,你会update
int finalRow = 0;
int finalColumn = 0;
int rNum = table.getSelectRow(); // 得到表格中被选中的行数
int cNum = table.getSelectColumn(); // 得到表格中被选中的列数
stmt = smple.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE); //创建可滚动,可更新的结果集
ResultSet select_rs = stmt.excutQuery(selectforupdate);
for (int i=0; i<finalRow; i++)
    selct_rs.next();
if(select_rs.next())
    select_rs.updateObject(finaleColumn,str);
select_rs.updateRow(); // 将结果落实到数据库(事务提交)

实现方法 2:

String str = "";
String selectForUpdate = "select empno,firstname,lastname,edlevel,job from jlu.employee for update";
int finalRow = 0;
int finalColumn = 0;
int rNum = table.getSelectRow(); // 得到表格中被选中的行数
int cNum = table.getSelectColumn(); // 得到表格中被选中的列数
stmt = smple.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
ResultSet select_rs=stmt.executeQuery(selectForUpdate);
select_rs.absolute(finalrow+1); //直接定位到第finalrow+1行
//select_rs.absolute(lastFianlrow); // 我记得有这个函数,就是定位到最后一行+1
select_rs.updateObject(finalcolmn+1,finalstr);
select_rs.updateRow();

知识点4:wasNull()方法

结果集返回的结果,如果使用String name = rs.getString(1);

再去判断name != null 的时候,判断的实际上是String类型的null,再String中“\0”就是空。

这样判断已经不是原来的rs是否为空了。

所以采用原有的rs.wasNull()可以判断是否读到的数据是空。

总结:就是wasNull()可以检查数据到底有没有读到。因为有时候那里的数据本来就是空,读到之后无法进行判断。例如我们单行插入的时候,很多数据并没有写进数据库。

try{
    PreparedStatement stmt = "";
    String sql = "UPDATE TEMPL SET PHONENO = ? WHERE EMPNO = '000110'";
    stmt = con.prepareStatement(sql);
    if (some condition)
    {
        stmt.setString(1,null);
        // stmt.setNUll(1,java.sql.Type.STRING);
    }else{
        stmt.setString(1,newPhone);
    }
    int updateCount = stmt.excuteUpdate();
    if (updateCOunt != 1)
    {
        JOptionPane.showMessageDialog(null,"报错");
    }
}catch(SQLException ex){
    ex.printStackTrace();
}

知识点5:结果集的进一步学习

5.1 使用last, previous,first遍历

String sql = "select * from staff";
PreparedStatement stmt = sample.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
rs.last(); // 最后一条
rs.previous(); // 向前遍历
rs.first(); // 第一个
rs.next(); // 下一个
rs.absolute(position); // 绝对位置position

5.2 批处理

Statement对于批处理留下了两个接口

  • void addBatch(String sql)

    相当于把sql添加到batch中一个一个执行。

  • int[] executeBatch()

    执行batch中的sql命令

Statement stmt = sample.createStatement();
stmt.addBatch(sql1);
stmt.addBatch(sql2);
stmt.addBatch(sql3);
int[] updateCounts = stmt.executeBatch(); // 返回的是影响数据库中行数的更新计数
sample.commit(); //提交事务

5.3 获取数据库结构

DatabaseMetaData dbmd = sample.getMetaData(); // 获取数据库结构
String[] tableTypes = {"TABLE","VIEW"};
ResultSet rs = dbmd.getTables(null,"UDBA","%",tableTypes);
/*
dbmd.getTables(String catalog,String schema,String tableName,String[] types)
String[] types想要返回何种表的数组
只会返回10字段的描述信息。
*/

知识点6:大对象(BLOB类型)的读取

6.1 blob对象作用

blob存放二进制字符串,适用于存放UDT(User-defined Distinct Types),因此我们可以存放图片,声音等等数据。blob对象取决于varchar的大小,varchar最大是2GB,因此blob, clob, dblob 的大小都限制在2GB。

一般来说,为了提高性能,数据库需要专门创建一个用于存放大字段的表空间,数据表的大字段列应该将数据存放于对应的表空间中,这是因为不经过内存(缓冲池)直接读取的。

6.2 BLOB类型的赋值

setBinaryStream(int n, java.io.InputStream x, int length)
// n指示参数编号的int
// InputStream对象
// length指示字节数的int

6.3 查询图片

代码逻辑:

先将Blob对象读取到rs结果集中,在用getBinaryStream()将Blob对象转换成二进制流对象inputStream;

之后将inputStream流对象通过.read()方法读到int c中,将c通过OutPutStream写到OutPutFile中。

Statement stmt = sample.createStatement();
ResultSet rs = st.excuteQuery("SELECT IMAGE FROM EMPLYEE");
while(rs.next())
{
    Blob blob = (Blob) rs.getBlob(1); // 读取Blob
    // Blob转换为数据流
    java.io.InputStream inputStream = blob.getBInaryStream(); 
    // 定义要写入的文件
    File fileOutPut = new File(path);
    FileOutPutStream fo = new FileOutPutStream(fileOutPut);
    int c;
    while((c = inputStream.read())!= -1)
        fo.write(c);
	fo.close();
}

6.4 插入图片

PreparedStatement pstm = conn.prepareStatement("insert into emp_photo where emptno = ?");
pstm.setString(emptnum);
File file = new File(path);
BufferedInputStream imageInput = new BufferedInputStream(new FileInputStream(file));
pstm.setBianryStream(1,imageInput,(int)file.length);
pstm.excuteUpdate();

知识点7:大对象(CLOB类型)的读取

7.1 clob的作用

存储字符串类型的数据。举例:resume中都是一部分一部分的。因此可以作为大对象存储。

Clob resumeLob = null; // 定义Clob
resumeLob = rs3.getClob(3); // 将结果集中第三个位置的Clob取出
String detailInfo = resumeLob.getSubString((long)),(int)resumeLob.length()); // 将Clob类型黄钻换成字符串类型
POSSTR(RESUME,'Personal')// 查看Personal在Resume中的位置
SUBSTR(RESUME,1,length); // 查看resume中1-length长度的字串
// 上面的两种语句详细用法
sql3 =
        "SELECT EMPNO, RESUME_FORMAT," +
        "SUBSTR(RESUME,1,?)|| SUBSTR(RESUME,?) AS RESUME " +
        "FROM JLU.EMP_RESUME " +
        "WHERE EMPNO = ? AND RESUME_FORMAT = 'ascii'";
/*
	因为我们只知道一部分的位置,可以用substr推断另一部分的位置
*/

这里的POSSTR和SUBSTR是在sql语句中增加的,详细的用法可以看老师给出的CLOB的示范代码。

知识点8:SQLException和SQLCODE

老师讲:数据库中很多代码都是进行错误处理的。因为没有一个代码是没有错误的,因此我们尽可能设计异常处理,来捕获错误,提高系统的鲁棒性。

8.1 SQLCODE和SQLSTATE

SQLCODE:是由数据库公司进行设计的,涵盖所有的SQLSTATE之外还可以附加其他的state;

SQLSTATE:是由国际标准组织指定的。

8.2 SQLException

是由jdbc创造的数据库异常捕获模块。

常见的用法及代码如下:

catch(SQLExecption sex){
    sex.printStackTrace();
    int SQLCODE = sex.getErrorCode();
    if(sex.getSQLState().equlas("23505"))
        JOPtionPane.showMeaasgeDialog(null,"主键重复");
}

常见的SQLCODE(DB2)

switch(SQLCODE){
            case 802:
                //数据溢出
                JOptionPane.showMessageDialog( null , "数据溢出" ,"SQL错误" , JOptionPane.ERROR_MESSAGE) ;
                break;
            case -007:
                //SQL语句中有非法字符
                JOptionPane.showMessageDialog( null , "SQL语句中有非法字符" ,"SQL信息" , JOptionPane.ERROR_MESSAGE) ;
                break;
            case -010:
                //丢失引号
                JOptionPane.showMessageDialog( null , "SQL语句丢失引号" ,"SQL信息" , JOptionPane.ERROR_MESSAGE) ;
                break;
            case -060:
                //某特定数据类型的长度或者标量规范无效
                JOptionPane.showMessageDialog( null , "某特定数据类型的长度或者标量规范无效" ,"SQL信息" , JOptionPane.ERROR_MESSAGE) ;
                break;
            case -102:
                //字符串常量太长
                JOptionPane.showMessageDialog( null , "字符串常量太长" ,"SQL信息" , JOptionPane.ERROR_MESSAGE) ;
                break;
            case -104:
                //SQL语句中遇到非法符号
                JOptionPane.showMessageDialog( null , "SQL语句中遇到非法符号" ,"SQL信息" , JOptionPane.ERROR_MESSAGE) ;
                break;
            case -433:
                //指定的值太长
                JOptionPane.showMessageDialog( null , "指定的值太长" ,"SQL信息" , JOptionPane.ERROR_MESSAGE) ;
                break;
            case -405:
                //数值文字超出了范围
                JOptionPane.showMessageDialog( null , "数值文字超出了范围" ,"SQL信息" , JOptionPane.ERROR_MESSAGE) ;
                break;
        }
  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AtonomyRay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值