PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

目录

 PB 的 JVM 配置(System Options)

 创建 MySQL 数据库 student (若已经创建请跳过,但最好跟我(课本)一样,要不然代码里要相应修改)

 JDBC 连接 MySQL

 建立工作空间

 创建数据窗口

 创建功能窗口

 生成可执行程序


如果你没有 董建全《数据库实用教程》(第三版)那你应该不会搜索这个教程,那么,我们是有缘人。

你已经准备好了 MySQL 数据库,但或许好不容易才准备好 PB ……

请准备好 JDBC 连接 MySQL 的驱动 jar 包:mysql-connector-java-5.1.46.jar (如已经有了就不需要再下载)

由于 PB 的原因,大概率会出现无法连接 64位 JDK 的问题,所以最好安装32位的 JDK 并配置好系统环境变量。

  • PB 的 JVM 配置(System Options)

点击导航栏顶部的 Tools,打开 System Options 并选择 Java,在 Classpaths 右侧点击虚线方框,在文件管理中选择你刚刚下载好的 jar 包,

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

 在右下方 Set JDK Location 中修改你安装的 JDK 的路径,以及相应的 JRE 路径,要注意只有32位的 JRE 中才有 client 文件

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

OK,在下方 JVM Status 中应该是这样的信息:

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

如果 Load Status 不是 Loaded 状态,那么之后连接数据库就会出现 PB 无法加载 JVM 的问题。

  • 创建 MySQL 数据库 student (若已经创建请跳过,但最好跟我(课本)一样,要不然代码里要相应修改)

其中各个表的设计如下:

c 表(课程表)

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

s 表(学生表)

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

sc 表(学生成绩表)

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

注意外键约束 :

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

  •  JDBC 连接 MySQL

打开 DataBase 

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

右键点击 JDB JDBC --> new profile 新建,在弹出的 Database Profile Setup - JDBC 窗口填写 JDBC 驱动以及你所要连接的数据库表的信息:

Driver Name:org.gjt.mm.mysql.Driver

URL:jdbc:mysql://localhost:3306/你要连接的数据库的名字

Login ID:你登录 MySQL 的用户名

Password:你登录 MySQL 的密码

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

OK,如果按照前面的配置,你已经连接上 MySQL 了,Tables 中有你创建好的表:

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

  •  建立工作空间

详情请参考《数据库实用教程》从 PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统 开始。

创建完成如图所示:

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

 双击 student.pbl 目录下的 student,右侧弹出 student 的 Application 窗口,左下角选择 open 填入以下代码,但先不要运行:

// Profile student
SQLCA.DBMS = "JDBC"
SQLCA.LogId = "root"
SQLCA.LogPass = "123456"
SQLCA.AutoCommit = False
SQLCA.DBParm = "Driver='org.gjt.mm.mysql.Driver', Url='jdbc:mysql://localhost:3306/student'"
//CONNECT;
connect using sqlca;
if SQLCA.SQLCODE<>0 then
	MessageBox("对不起,链接不了数据库", SQLCA.SQLERRTEXT)
	halt
	return
else
	s_info = 's1'
	open(w_select_course)
// 下面这行代码在创建了 w_login 后用到,届时要注释掉上面两行
	//open(w_login)
end if
  •  创建数据窗口

我傻逼了,这些教程就在书里啊……,此部分详情请参考 董建全《数据库实用教程》(第三版)PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统 - PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

学生成绩报告单(d_student_score_report)数据窗口,以及成绩分布(d_score_dis)数据窗口要仔细看PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统课本中的 图13.49 以及图 13.50 中的复选框选择和计算公式,以及各个字段的摆放,否则,不好看。

  • 创建功能窗口

进行这里之前你要从课本的 PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统 跟着教程走到 PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统 。

创建窗口,添加控件、绑定数据窗口这些,都完全跟着课本教程走,但是代码都用我的,因为是完整的。

  • 编写应用对象(student.pbl)的脚本:

我们在上面已经在 open 窗口中打了代码,不需要重复。

接下来选择 PB 主窗口中 “View” 菜单下的 “Variable” 子菜单,打开 “Declare Instance Variable” 子窗口,在下拉列表框中选择 “Global Variable”,在窗口空白区域输入全局变量:

string s_info, s_credit, c_info, cname_info, teacher
  • “学生选课”主窗口 w_select_course:

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

open 事件脚本:

// 窗口 w_select_course 的 open 事件
dw_1.settransobject(sqlca)
dw_1.retrieve(s_info)
dw_1.object.datawindow.readonly = 'yes'
dw_2.settransobject(sqlca)
dw_2.retrieve(s_info)
dw_2.object.datawindow.readonly = 'yes'
dw_3.settransobject(sqlca)
dw_3.retrieve(s_info)
dw_3.object.datawindow.readonly = 'yes'
dw_4.settransobject(sqlca)
dw_4.retrieve(s_info)
dw_4.object.datawindow.readonly = 'yes'
sle_1.SetFocus( )

 选课按钮 clicked 脚本:

// 选课按钮 pb_1 的 clicked 事件脚本
string ccname, ccno
c_info = upper(sle_1.text)
if c_info = "" then
	MessageBox("出错", "请输入课程号")
else
	select c.cname into :ccname from c where c.cno = :c_info;
	if SQLCA.SQLCODE <> 0 then
		MessageBox("出错", "此课程号不存在")
	else
		select sc.cno into :ccno from sc where (sc.cno = :c_info and 
		sc.sno = :s_info);
		if SQLCA.SQLCODE = 0 then
			MessageBox("出错", "此课程已选")
		else
			INSERT INTO sc (sno, cno)
			VALUES (:s_info, :c_info);
			dw_4.reset()
			sle_1.text = ""
			dw_4.settransobject(sqlca)
			dw_4.retrieve(s_info)
		end if
	end if
end if

退课按钮 clicked 脚本:

// 退课 pb_2 clicked 脚本
string ccno, ggrade
if sle_1.text = "" then
	MessageBox("出错", "请输入课程号")
end if
c_info = upper(sle_1.text)
if c_info <> "" then
	select c.cname into :cname_info from c where c.cno = :c_info;
	if SQLCA.SQLCODE <> 0 then
		MessageBox("出错", "此课程号不存在")
	else
		select sc.cno, sc.grade into :ccno, :ggrade from sc where (sc.cno = :c_info and
		sc.sno = :s_info);
		if SQLCA.SQLCODE <> 0 then
			MessageBox("出错", "此课程未选")
		else
			if ggrade <> "" then
				MessageBox("出错", "此课程已登分")
			else
				delete from sc where sno = :s_info and cno = :c_info;
				dw_4.reset()
				sle_1.text = ""
				dw_4.settransobject(sqlca)
				dw_4.retrieve(s_info)
			end if
		end if
	end if
end if

可选课程 doubleclicked 脚本:

// 可选课程 dw_2 的 doubleclicked 脚本:
open(w_select_student_score_report)

关闭按钮我都觉得没必要。

  • “课程信息”窗口 w_course_create :

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

 open 事件脚本:

// 课程信息窗口 w_course_create 的 open 事件脚本
int sum, hascol
dw_1.settransobject(sqlca);
dw_1.retrieve();
hascol = dw_1.retrieve();
pb_2.enabled = false
st_1.text = string(hascol)

新增按钮 clicked 脚本:

// 新增按钮 pb_1 的 clicked 事件脚本
long l_row
int s
pb_1.enabled = false
s = dw_1.RowCount()
l_row = dw_1.InsertRow(s+1)
dw_1.scrolltorow(s+1)
dw_1.setfocus()
pb_1.enabled = false
pb_2.enabled = true

 保存按钮 clicked 脚本:

// 保存按钮 pb_2 的 clicked 事件脚本
int s, hascol
string kk
s = dw_1.getrow();
c_info = dw_1.getitemstring(s, "cno")
select c.cno into :kk from c where (c.cno = :c_info);
if c_info = kk then
	MessageBox("出错", "不能增加,此课程号已经存在")
else
	dw_1.update()
	hascol = dw_1.retrieve()
	st_1.text = string(hascol)
	pb_1.enabled = true
	pb_2.enabled = false
end if

 删除按钮 clicked 脚本:

// 删除按钮 pb_3 的 clicked 事件脚本
int s, hascol
string kk
s = dw_1.getrow();
c_info = dw_1.getitemstring(s, "cno")
select sc.cno into :kk from sc where (sc.cno = c_info);
if c_info = kk then
	MessageBox("出错", "不能删除,此课程已经有学生选")
else
	dw_1.DeleteRow(s);
	dw_1.update();
	hascol = dw_1.retrieve();
	st_1.text = string(hascol)
end if
pb_1.enabled = true
pb_2.enabled = false
  •  “学生信息”窗口 w_student_create:

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

 open 事件脚本:

// 学生信息窗口 w_student_create 的 open 事件脚本
int sum, hascol
dw_1.settransobject(sqlca);
dw_1.retrieve();
hascol = dw_1.retrieve();
pb_2.enabled = false
st_1.text = string(hascol)

 新增按钮 clicked 脚本:

// 新增按钮 pb_1 的 clicked 事件脚本
long l_row
int s
s = dw_1.RowCount()
l_row = dw_1.InsertRow(s+1)
dw_1.scrolltorow(s+1)
dw_1.setfocus()
pb_1.enabled = false
pb_2.enabled = true

 保存按钮 clicked 脚本:

// 保存按钮 pb_2 的 clicked 事件脚本
int s, hascol;
string kk
s = dw_1.getrow();
s_info = dw_1.getitemstring(s, "sno")
select s.sno into :kk from s where (s.sno = :s_info);
if s_info = kk then
	MessageBox("出错", "不能增加,此学号已存在")
else
	dw_1.update()
	hascol = dw_1.retrieve()
	st_1.text = string(hascol)
	pb_1.enabled = true
	pb_2.enabled = false
end if

 删除按钮 clicked 脚本:

// 删除按钮 pb_3 的 clicked 事件脚本
int s, hascol;
string kk
s = dw_1.getrow();
s_info = dw_1.getitemstring(s, "sno")
select sc.sno into :kk from sc where (sc.sno = s_info);
if s_info = kk then
	MessageBox("出错", "不能删除,此学生已经选课")
else
	dw_1.DeleteRow(s)
	dw_1.Update()
	hascol = dw_1.retrieve();
	st_1.text = string(hascol)
end if
pb_1.enabled = true
pb_2.enabled = false
  •  “学生成绩单”子窗口 w_select_student_score_report :

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

 open 事件脚本:(课本中没有,但这是必要的……太坑了)

// 学生成绩单窗口 w_select_student_score_report 的 open 事件脚本
dw_1.settransobject(sqlca)
dw_1.retrieve(s_info)
dw_1.object.datawindow.readonly="yes"
  •  “成绩分布”子窗口 w_course_score_dis: 

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

 open 事件脚本:(太坑了……)

// 成绩分布子窗口 w_course_score_dis 的 open 事件脚本
dw_1.settransobject(sqlca)
dw_1.retrieve(s_info)
dw_1.object.datawindow.readonly="yes"
  • “成绩管理”主窗口 w_teacher_manage:

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

 open 事件脚本:

// 成绩管理主窗口 w_teacher_manage 的 open 事件脚本
declare cnamecursor cursor for
	select distinct c.cname
	from c, sc
	where c.cno = sc.cno;
open cnamecursor;
if sqlca.sqlcode = -1 then
	MessageBox("sql error", string(sqlca.sqldbcode) + ":" + sqlca.sqlerrtext)
else
	cname_info = ""
	do
		if cname_info <> "" then
			ddlb_cname.additem(cname_info)
		end if
		fetch cnamecursor into :cname_info;
	loop while sqlca.sqlcode = 0
	if sqlca.sqlcode = -1 then
		MessageBox("sql error", string(sqlca.sqldbcode) + ":" + sqlca.sqlerrtext)
	end if
end if
close cnamecursor;
pb_2.enabled = false

查询按钮 clicked 脚本:

// 查询按钮 pb_1 的 clicked 事件脚本
if ddlb_cname.text = "" then
	MessageBox("出错", "请选择课程名")
else
	cname_info = upper(ddlb_cname.text)
	select cno, tname into :c_info, :teacher
	from c
	where cname = :cname_info;
	st_5.text = ddlb_cname.text
	st_6.text = teacher
	dw_1.settransobject(sqlca)
	dw_1.retrieve(c_info)
	dw_1.object.datawindow.readonly = "yes"
	pb_2.enabled = true
end if

输入成绩按钮 clicked 脚本:

// 输入成绩 pb_2 的 clicked 事件脚本
if pb_2.text = '输入成绩' then
	// 有这一句才能编辑成绩:(太坑了……)
	dw_1.modify( "grade.TabSequence = 10" )
	dw_1.object.datawindow.readonly = 'no'
	pb_2.text = '保存'
	pb_1.enabled = false
	pb_3.enabled = false
	st_4.text = '请输入成绩:'
else
	dw_1.UPDATE()
	dw_1.retrieve(c_info)
	dw_1.object.datawindow.readonly = 'yes'
	pb_2.text = '输入成绩'
	pb_1.enabled = true
	pb_2.enabled = true
	pb_3.enabled = true
	st_4.text = "已选修此课的学生:"
end if

成绩分布按钮 clicked 脚本:

// 成绩分布按钮 pb_3 clicked 事件脚本
open(w_course_score_dis)
  • 登录窗口 w_login:

PowerBuilder 使用 JDBC 连接 MySQL 实现学生选课管理系统

open 事件我没图,没写

sle_user 控件 checkkey 或 modified 脚本:

// w_login 窗口的 sle_user 控件 checkkey 或 modified 事件脚本
if keydown(KeyEnter!) then
	sle_pwd.setfocus()
end if

sle_pwd 控件 checkkey 脚本:

// w_login 窗口的 sle_pwd 控件 checkkey 事件脚本
if keydown(KeyEnter!) then
	pb_login.setfocus()
end if

登录按钮 pb_login 的 clicked 脚本:

// 登录按钮 pb_login 的 clicked 事件脚本
if sle_user.text = "" then
	MessageBox("提醒", "请输入用户名")
	sle_user.setfocus()
	return
end if
if sle_pwd.text = "" then
	MessageBox("提醒", "请输入密码")
	sle_pwd.setfocus()
	return
end if
string ls_user, ls_pwd, ls_confirm_user, ls_confirm_pwd
// 此处做了修改,system 用户登录不要大写
// ls_user = upper(sle_user.text)
// ls_pwd = upper(sle_pwd.text)
ls_user = sle_user.text
ls_pwd = sle_pwd.text
ls_confirm_pwd = ""
ls_confirm_user = ""
if (ls_user = 'system' and ls_pwd = 'system') then
	open(w_teacher_manage)
	close(parent)
else
// 此处 SQL 语句中的双引号去掉了
	select s.logn, s.pswd, s.sno
	into :ls_confirm_user, :ls_confirm_pwd, :s_info
	from s where s.logn = :ls_user;
	s_info = trim(s_info)
	if ls_user <> trim(ls_confirm_user) then
		MessageBox("警告!", "用户名错,重新注册", stopSign!)
		sle_user.text = ""
		sle_pwd.text = ""
		sle_user.setfocus()
	elseif ls_pwd <> trim(ls_confirm_pwd) then
		MessageBox("警告!", "密码错误,重新注册", stopSign!)
		sle_pwd.text = ""
		sle_pwd.setfocus()
	else
		open(w_select_course)
		close(parent)
	end if
end if

退出按钮的 clicked 脚本:

// 退出按钮 pb_exit 的 clicked 事件脚本
close(parent)
  • 修改应用对象(student.pbl)的脚本(前面有过注释):
// student 脚本修改
s_info = 's1'
open(w_select_course)

// 注释掉上面两句,修改为:
open(w_login)

可以运行了。

之后添加菜单的教程可以跟着课本走了,前面的坑基本都踩过了。

  • 生成可执行程序

放弃吧弟弟,这里 PB 操作 MySQL 数据库是通过 settransobject(sqlca),遗憾的是 MySQL 并不支持环境外的这种操作,所以生成 exe 文件后执行会报错,在下至今无解。我们只能在 PB 里面运行这个项目。但是我知道你没有愁眉苦脸,因为老师验收时不会关心这个。