文章目录
- 绪:
- 成品样例
- 项目要求
- 项目分析
- 1. MySQL数据库
- 2. GUI各个窗口的功能
- 代码实现
- JavaBean类
- 1.【tickets.java】
- 2.【person.java】
- 3.【administrator.java】
- 窗口
- 一、 主窗口【Window.java】
- 事件监听
- 1. 窗口启动,读取【tickets表】,TextArea显示
- 2. 查询按钮
- 3. 刷新按钮
- 4. 购买按钮
- 5. 智能购票系统后台管理按钮
- 二、购买窗口【PayWindow.java】
- 事件监听
- 1. 窗口启动,TextArea显示【person表】中的信息,每日一言
- 2. 提交信息按钮
- 3.下单按钮
- 三、管理员登录窗口【Login.java】
- 事件监听
- 1. 登录按钮
- 四、加载登录窗口【LoadLogin.java】
- 事件监听
- 五、修改车票窗口【UpadateTicketWindow.java】
- 事件监听
- 1. 显示当前登录用户
- 2. 插入单个车票
- 3.修改单个车票
- 4.批量插入车票
- 5. 批量修改车票
- 6. 删除单个车票
- 7. 删除所有车票
- 8. 超链接
- 六、添加单个车票窗口【InsertWindow.java】
- 事件监听
- 1.添加车票
- 七、修改单个车票窗口【updateWindow.java】
- 事件监听
- 1.修改
- 八、删除所有车票窗口【deleteWindow.java】
- 事件监听
- 1.清空所有车票信息
- 2.清空所有历史信息
- DEMO源码
绪:
Java使用多线程和GUI实现购买火车票<集合>
之前写了一个用Map集合来存储车票和顾客的信息,有点简陋,不过很基础。所以在上一次的基础上加了点东西,连接了数据库。下面是用到的环境
配置环境
- JDK1.8
- MySQL 8.0
- JDBC驱动 8.0.22
- Apache-DBUtils的API 1.6
- Druid驱动包1.1.10
连接数据库就需要用到jdbc,为了方便,用了连接池,为了实现多窗口,使用了线程池
至于如何学习JDBC和下载驱动,送上文章连接:
- JDBC驱动 8.0.22
- JDBC驱动下载地址
成品样例
项目要求
- 文本文件提供票的信息,车次、票价、始发站终点站、票数
- 启动程序,首先读取文件,放入TextArea中,如果车次较多,那么需要加滚动条(上述两步骤,用到的是文件读写IO)
- 输入车次,查找该车次,并显示信息
如何在文本域中找出相关信息,并且读出这一条信息——字符串操作 - 找到车次了,输入购买张数,点击购买,弹出新的窗口——新的窗口是启动了一个线程——多线程
- 在购买界面,显示购买车次的信息,和顾客进行确认。并且提供身份证信息
如果买多张,那么这些身份证信息,先保存到集合中(map),遍历集合,给每个身份证购买一张票 - 输出购买信息
项目分析
因为这次要连接数据库操作,那么就需要建立对应的表存储信息,
首先了解两种思想
- 面向接口编程的思想
- ORM思想(object relational mapping)
- 一个数据表对应一个java类
- 表中的一条记录对应java类的一个对象
- 表中的一个字段对应java类的一个属性
即数据库中的一个数据表对应着java的javabean类
sql是需要结合列名和表的属性名来写。注意起别名。
1. MySQL数据库
- 【ticket数据库】
- 【tickets表】
存储所有车票信息
- 【person表】
存储所有购买车票的顾客信息
- 【administrator表】
存储管理员的账号密码
2. GUI各个窗口的功能
根据上一次的经验,这次又要连接数据库,所以我分了下功能
- 主窗口【Window.java】
- 文本文件提供票的信息,车次、票价、始发站终点站、票数
- 启动程序,首先读取文件,放入TextArea中,如果车次较多,那么需要加滚动条
- 查询车票
- 购买窗口【PayWindow.java】
- 显示提交的顾客信息
- 根据提交的顾客信息购买车票
- 管理员登录窗口【Login.java】
- 管理员输入账号密码登录
- 修改车票窗口【UpadateTicketWindow.java】
修改车票窗口【UpadateTicketWindow.java】是用于 后台对车票信息的管理,包含以下功能
- 插入单个车票
- 修改单个车票
- 批量插入车票
- 批量修改车票
- 删除单个车票
- 批量删除信息(所有车票信息,所有历史购买信息)
因为拥有插入,修改,删除功能,我又想做的好看点,便于与用户交互,就每个又分别写了个窗口
- 加载登录窗口【LoadLogin.java】
在管理员登录窗口【Login.java】和修改车票窗口【UpadateTicketWindow.java】之间加入了一个登录进度条窗口【LoadLogin.java】没什么用,只是为了好看
- 显示登录进度条
代码实现
既然了解了ORM思想,那么数据库有3个数据表【tickets表】,【person表】,【administrator表】,所以对应的需要建3个类【tickets.java】,【person.java】,【administrator.java】
JavaBean类
1.【tickets.java】
public class Tickets {
private String name; // 车票名
private String start; // 起始站
private String end; // 终点站
private int number; // 数量
private double price; // 价格
public Tickets(String name, String start, String end, double price, int number) {
super();
this.name = name;
this.start = start;
this.end = end;
this.number = number;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStart() {
return start;
}
public void setStart(String start) {
this.start = start;
}
public String getEnd() {
return end;
}
public void setEnd(String end) {
this.end = end;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Tickets() {
super();
}
@Override
public String toString() {
return "Ticket [name=" + name + ", start=" + start + ", end=" + end + ", number=" + number + ", price=" + price
+ "]";
}
}
2.【person.java】
import java.sql.Date;
import java.sql.Timestamp;
public class Person {
private String name; // 姓名
private String IDCard; // 身份证号
private String ticketname; // 车票名
private String start; // 起始站
private String end; // 终点站
private double price; // 车票的价钱
private Timestamp date;// 时间戳
public Person(String name, String iDCard, String ticketname, String start, String end, double price,
Timestamp date) {
super();
this.name = name;
IDCard = iDCard;
this.ticketname = ticketname;
this.start = start;
this.end = end;
this.price = price;
this.date = date;
}
public Timestamp getDate() {
return date;
}
public void setDate(Timestamp date) {
this.date = date;
}
public Person() {
super();
}
public Person(String name, String iDCard) {
super();
this.name = name;
IDCard = iDCard;
}
public Person(String name, String iDCard, String ticketname, String start, String end, double price) {
super();
this.name = name;
this.IDCard = iDCard;
this.ticketname = ticketname;
this.start = start;
this.end = end;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIDCard() {
return IDCard;
}
public void setIDCard(String iDCard) {
IDCard = iDCard;
}
public String getTicketname() {
return ticketname;
}
public void setTicketname(String ticketname) {
this.ticketname = ticketname;
}
public String getStart() {
return start;
}
public void setStart(String start) {
this.start = start;
}
public String getEnd() {
return end;
}
public void setEnd(String end) {
this.end = end;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Person [name=" + name + ", IDCard=" + IDCard + ", ticketname=" + ticketname + ", start=" + start
+ ", end=" + end + ", price=" + price + "]";
}
}
3.【administrator.java】
public class Administrator {
private String username;
private String password;
public Administrator(String username, String password) {
super();
this.username = username;
this.password = password;
}
public Administrator() {
super();
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Administrator [username=" + username + ", password=" + password + "]";
}
}
窗口
一、 主窗口【Window.java】
主窗口的布局和上次没什么改变,只是加了智能购票系统后台管理按钮
事件监听
因为窗口启动时显示【tickets表】的所有车票信息,查找也需要显示车票信息,刷新也要显示车票信息,因此将显示车票信息写成了一个方法,仅需要传入用于显示信息的TextArea, 和要执行的sql语句,用于需要输出车票信息时调用,方法如下:
// 打印tickets数据表中的所有车票信息
public void loadticket(JTextArea textArea, String sql) {
Connection con = null;
try {
// 获取连接
con = source.getConnection();
BeanListHandler<Tickets> ticketbean = new BeanListHandler<Tickets>(Tickets.class);
//调用QueryRunner类的方法执行sql语句,返回ticketbean组成的集合
List<Tickets> ticketlist = runner.query(con, sql, ticketbean);
//迭代器遍历集合,输出信息
Iterator<Tickets> iter = ticketlist.iterator();
String ticstr = "";
while (iter.hasNext()) {
Tickets ticket = iter.next();
ticstr += " " + ticket.getName() + "\t" + ticket.getStart() + "\t" + ticket.getEnd() + "\t"
+ ticket.getPrice() + "\t" + ticket.getNumber() + "\n";
}
textArea.setText(ticketload + ticstr);
} catch (SQLException e1) {
e1.printStackTrace();
} finally {
// 释放连接
DbUtils.closeQuietly(con);
}
}
1. 窗口启动,读取【tickets表】,TextArea显示
窗口加载事件【windowOpened】,读取ticket数据库中,【tickets表】中存储的所有车票信息,TextArea显示
// 窗口加载事件
addWindowListener(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
//调用loadticket()方法
String sql = "SELECT * FROM tickets";
loadticket(textArea, sql);
}
});
2. 查询按钮
根据输入的信息,模糊查询【tickets表】,TextArea显示查询的结果
// 查找按钮
button_search.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
//获取用户输入的信息
String text = searchText.getText();
//调用loadticket()方法
String sql = "SELECT * FROM tickets WHERE NAME LIKE '%" + text + "%'";
loadticket(textArea_1, sql);
}
});
3. 刷新按钮
更新TextArea显示的信息
// 刷新按钮
shuaxin.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
//调用loadticket()方法
String sql = "SELECT * FROM tickets";
loadticket(textArea, sql);
}
});
4. 购买按钮
打开购买窗口【PayWindow.java】
// 购买按钮
button_buy.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
Connection con = null;
try {
//获取 Druid连接池的连接
con = source.getConnection();
PayWindow pw = new PayWindow(con);
new Thread(pw).start();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
});
5. 智能购票系统后台管理按钮
打开管理员登录窗口【Login.java】
/**
* 后台
*/
btnNewButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
Connection con = null;
try {
// 获取Druid连接池的连接
con = source.getConnection();
Login frame = new Login(con);
new Thread(frame).start();
} catch (SQLException e) {
e.printStackTrace();
}
}
});
二、购买窗口【PayWindow.java】
购买窗口也在之前的基础上加了显示历史购买车票信息和每日一言(每3s刷新一次)
事件监听
因为窗口加载时要显示历史购买信息,以及每次下单成功后自动更新历史购买的信息,因此也写了一个方法,需要传一个Connection连接和要显示的JTextArea
public void show(Connection con, JTextArea textArea) {
// 遍历输出【person表】中的信息
String li = "";
try {
BeanListHandler<Person> personbeanlist = new BeanListHandler<Person>(Person.class);
String sql = "SELECT * FROM person ORDER BY ticketname;";
List<Person> personlist = runner.query(con, sql, personbeanlist);
Iterator<Person> iter = personlist.iterator();
while (iter.hasNext()) {
Person person = iter.next();
li += " " + person.getName() + " " + person.getIDCard().substring(0, 6) + "******"
+ person.getIDCard().substring(14) + "\t" + person.getTicketname() + " " + person.getStart()
+ " " + person.getEnd() + " " + person.getPrice() + " " + person.getDate() + "\n";
}
textArea.setText(personlist3 + li);
} catch (SQLException e1) {
e1.printStackTrace();
}
}
1. 窗口启动,TextArea显示【person表】中的信息,每日一言
窗口启动,显示历史购买信息,和每日一言(每3s刷新)
@Override
public void windowOpened(WindowEvent e) {
/**
* 输出personMap集合的信息
*/
show(con, textArea_1);
//List加载每日一言文件
strList.clear();
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader("src//每日一言");
br = new BufferedReader(fr);
String str = null;
while ((str = br.readLine()) != null) {
strList.add(str);
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
}
// 定时显示每日一言
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
Random rand = new Random();
int nextInt = rand.nextInt(strList.size() - 1);
lblNewLabel.setText(strList.get(nextInt));
}
}, 1000, 3000);//初始1s定时,以后定时3s
}
2. 提交信息按钮
将输入的姓名和身份证号添加到集合,并显示在TextArea中,根据提交信息的数量来决定购票的数量
// 提交信息
btnNewButton_subbmit.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
String name = textField_name.getText();
String idcard = textField_IDCard.getText();
String select = "select IDCard from person where IDCard=?";
// 如果两个文本框不为空则添加信息到队列
if (!"".equals(name) && !"".equals(idcard)) {
if (personMap.containsKey(idcard)) {
int n = JOptionPane.showConfirmDialog(null, "提交信息已存在,是否覆盖", "信息提示", JOptionPane.YES_NO_OPTION);
if (n == 0) {
personMap.put(idcard, new Person(name, idcard));
}
} else {
// 用获取到的姓名和身份证号生成对象,添加到存储顾客对象的Map集合中
personMap.put(idcard, new Person(name, idcard));
}
String li = "";
// 遍历Map集合,获取集合中顾客的所有信息
Set<Map.Entry<String, Person>> set = personMap.entrySet();
Iterator<Entry<String, Person>> setItor = set.iterator();
while (setItor.hasNext()) {
Person person = setItor.next().getValue();
// 将顾客的所有的信息拼接成字符串
li += " " + person.getName() + " " + person.getIDCard().substring(0, 6) + "******"
+ person.getIDCard().substring(14) + "\n";
}
// 5.textArea显示拼接的字符串
textArea.setText(personlist1 + li);
} else {
JOptionPane.showMessageDialog(null, name + idcard + "信息不完整", name + idcard, 0);
}
}
});
}
3.下单按钮
实现购票,根据提交信息的名单依次购买车票,如果出错则事务回滚
// 下单按钮
btnNewButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
// 判断信息是否填写,
String ticketname = textField.getText();
if (ticketname != null && personMap.size() > 0) {
System.out.println(personMap.size());
try {
BeanHandler<Tickets> ticBean = new BeanHandler<Tickets>(Tickets.class);
Tickets tic = runner.query(con, selecttickets, ticBean, ticketname);
ticketMap.put(ticketname, tic);
if (tic != null) {
int n = 0;
if (tic.getNumber() < personMap.size()) {
n = JOptionPane.showConfirmDialog(null,
"车票剩余不够购买数量,目前剩余数量:" + tic.getNumber() + ",如果继续购买则先买先得", "",
JOptionPane.YES_NO_OPTION);
}
if (n == 0) {
int a = JOptionPane
.showConfirmDialog(null,
"按照已提交信息名单收取金额(若未购买到票则退还相应的金额),应支付金额:"
+ personMap.size() * tic.getPrice() + ",是否确认支付",
"支付窗口", JOptionPane.YES_NO_OPTION);
if (a == 0) {
con.setAutoCommit(false);
// 购票环节
Set<Map.Entry<String, Person>> entrySet = personMap.entrySet();
for (Map.Entry<String, Person> set : entrySet) {
Tickets tic1 = runner.query(con, selecttickets, ticBean, ticketname);
try {
if (tic1.getNumber() > 0) {
runner.update(con, update, tic1.getNumber() - 1, ticketname);
Person person = set.getValue();
person.setTicketname(ticketname);
person.setStart(tic1.getStart());
person.setEnd(tic1.getEnd());
person.setPrice(tic1.getPrice());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
java.util.Date date = sdf.parse(sdf.format(System.currentTimeMillis()));
Timestamp time = new Timestamp(date.getTime());
person.setDate(time);
runner.update(con, insert, person.getName(), person.getIDCard(),
person.getTicketname(), person.getStart(), person.getEnd(),
person.getPrice(), time);
con.commit();
}
} catch (Exception e1) {
e1.printStackTrace();
// 数据库事务回滚
con.rollback();
}
}
/**
* 输出personMap集合的信息
*/
String li = "";
// 遍历Map集合,获取集合中顾客的所有信息
Set<Map.Entry<String, Person>> set = personMap.entrySet();
Iterator<Entry<String, Person>> setItor = set.iterator();
while (setItor.hasNext()) {
Person person = setItor.next().getValue();
// 将顾客的所有的信息拼接成字符串
li += " " + person.getName() + " " + person.getIDCard().substring(0, 6)
+ "******" + person.getIDCard().substring(14) + " "
+ person.getTicketname() + " " + person.getPrice() + "\n";
}
// textArea显示拼接的字符串
textArea.setText(personlist2 + li);
personMap.clear();
show(con, textArea_1);
con.setAutoCommit(true);
}
}
} else {
JOptionPane.showMessageDialog(null, "未找到该车次", "", 0);
}
} catch (SQLException e1) {
e1.printStackTrace();
}
} else {
JOptionPane.showMessageDialog(null, "未填写信息或未提交信息", "", 0);
}
}
});
三、管理员登录窗口【Login.java】
由主窗口【Window.java】点击【智能购票系统后台管理按钮】打开,用户输入用户名和密码
事件监听
1. 登录按钮
获取输入的用户名和密码,显示进度条
//登录点击按钮,进行登录
btnNewButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
String name = textField.getText();
String password = textField_1.getText();
try {
//判断用户名和密码是否为空
if (!"".equals(name) && !"".equals(password)) {
//启动登录进度条,传入输入的用户名和密码
Loadlogin load = new Loadlogin(con, name, password);
new Thread(load).start();
//销毁窗口
dispose();
} else {
JOptionPane.showMessageDialog(null, "请输入信息", "ERROR", 0);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
四、加载登录窗口【LoadLogin.java】
一个进度条,同时拿获取的用户名和密码和数据库中的【administrator表】进行信息比对
如果都存在则登录成功,进入修改车票窗口【UpadateTicketWindow.java】
如果失败,则返回管理员登录窗口【Login.java】
事件监听
显示进度条,同时拿获取的用户名和密码和数据库中的【administrator表】进行信息比对
addWindowListener(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent arg0) {
//定时器,3s
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
String sql = "SELECT password FROM administrator WHERE username=?";
BeanHandler<Administrator> bh = new BeanHandler<Administrator>(Administrator.class);
Administrator admin = null;
try {
//进行数据库查询
admin = runner.query(con, sql, bh, name);
//如果用户存在并且输入的用户名和密码正确
if (admin != null && admin.getPassword().equals(password)) {
//如果存在,则进度条显示登录成功
jpg.setString("登录成功");
Thread.sleep(1000);
dispose();
//显示修改车票窗口【UpadateTicketWindow.java】
UpadateTicketWindow upadateTicketWindow = new UpadateTicketWindow(con,name);
new Thread(upadateTicketWindow).start();
} else {
//如果不存在,则进度条显示登录失败
jpg.setString("登录失败");
Thread.sleep(1000);
dispose();
//返回管理员登录窗口【Login.java】
Login login = new Login(con);
new Thread(login).start();
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
}, 3000);
}
});
五、修改车票窗口【UpadateTicketWindow.java】
对信息的单个增删改和批量增删改,每个按钮对应一种操作
事件监听
批量操作涉及到的公用方法,【JFileChooser】选择文件,【IO流】读取文件
/**
* 选择文件,读取文件信息,存放到ticList
*/
public List selcetfile() {
FileReader fr = null;
BufferedReader br = null;
try {
// 打开文件选择器
JFileChooser jfc = new JFileChooser();
FileFilter filter = new FileNameExtensionFilter("Text file", "txt");
// 过滤txt文件
jfc.setAcceptAllFileFilterUsed(false);
jfc.addChoosableFileFilter(filter);
jfc.showOpenDialog(null);
File file = jfc.getSelectedFile();
if (file != null) {
List<Tickets> ticList = new ArrayList<Tickets>();
fr = new FileReader(file);
br = new BufferedReader(fr);
String str = null;
//读取文件每一行,分析,并创建ticket对象存储到 List集合
while ((str = br.readLine()) != null) {
String[] split = str.split("\t");
Tickets tic = new Tickets(split[0], split[1], split[2], Double.parseDouble(split[3]),
Integer.parseInt(split[4]));
ticList.add(tic);
}
//返回添加数据之后的ticList
return ticList;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (br != null)
br.close();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
if (fr != null)
fr.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
return null;
}
1. 显示当前登录用户
窗口启动,则显示目前登录的管理员用户信息
@Override
public void windowOpened(WindowEvent arg0) {
lblNewLabel_3.setText(name);
}
2. 插入单个车票
因为插入单个车票涉及了车票的各种信息,所以加了一个窗口【InsertWindow.java】
点击按钮则启动【InsertWindow.java】窗口,让用户来添加信息
/**
* 添加车票信息
*/
Button_insertOne.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
InsertWindow iw = new InsertWindow(con);
new Thread(iw).start();
}
});
3.修改单个车票
和插入单个车票操作类似,涉及车票的信息,加了一个修改窗口【updateWindow.java】
点击按钮则启动【updateWindow.java】窗口,让用户来输入修改的信息,根据车次名修改
// 修改单个数据
Button_updateOne.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
updateWindow updateWindow = new updateWindow(con);
new Thread(updateWindow).start();
}
});
4.批量插入车票
一次性插入多个车票信息,原理是读取并插入【车次.txt文件】中的所有车票信息
当然了,添加过程中,使用的是【DBUtils】提供的batch
批量方法。考虑到了批量插入中途又可能会出现错误,加入了事务回滚,如果中途出现错误,则数据库数据回滚到上次提交之后的数据,因为数据库一旦提交则不可重现,所以需要关闭数据库的自动提交
// 批量插入
Button_BatchInset.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
String insert = "INSERT INTO tickets(name,start,end,price,number) VALUES(?,?,?,?,?)";
try {
//关闭事务自动提交
con.setAutoCommit(false);
//调用selcetfile()读取文件,加载到集合
List<Tickets> ticList = selcetfile();
String[][] strss = new String[ticList.size()][5];
for (int i = 0; i < ticList.size(); i++) {
Tickets tic = ticList.get(i);
strss[i][0] = tic.getName();
strss[i][1] = tic.getStart();
strss[i][2] = tic.getEnd();
strss[i][3] = tic.getPrice() + "";
strss[i][4] = tic.getNumber() + "";
}
runner.batch(con, insert, strss);
//事务手动提交
con.commit();
//开启事务自动提交
con.setAutoCommit(true);
JOptionPane.showMessageDialog(null, "批量添加成功", "批量添加", 1);
} catch (Exception e1) {
try {
con.rollback();
} catch (SQLException e2) {
e2.printStackTrace();
}
}
}
});
5. 批量修改车票
一次性修改文件存储的车次信息,读取【修改的车次.txt文件】中的所有车票信息,根据车次名修改。
和批量插入一样,修改过程中,使用的是【DBUtils】提供的batch
批量方法。考虑到了批量修改中途又可能会出现错误,加入了事务回滚,如果中途出现错误,则数据库数据回滚到上次提交之后的数据,因为数据库一旦提交则不可重现,所以需要关闭数据库的自动提交
// 批量修改
Button_updatemore.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
// 修改
String update = "UPDATE tickets SET START=?,END=?,price=?,NUMBER=? WHERE NAME=?";
// runner.b
try {
// 关闭事务自动提交
con.setAutoCommit(false);
// 读取文件,信息存到ticList
List<Tickets> ticList = selcetfile();
// 将车票的信息存储到二维数组,
String[][] strss = new String[ticList.size()][5];
for (int i = 0; i < ticList.size(); i++) {
Tickets tic = ticList.get(i);
strss[i][0] = tic.getStart();
strss[i][1] = tic.getEnd();
strss[i][2] = tic.getPrice() + "";
strss[i][3] = tic.getNumber() + "";
strss[i][4] = tic.getName();
}
// QueryRunner,batch批量执行
runner.batch(con, update, strss);
// 事务提交
con.commit();
// 开启事务自动提交
con.setAutoCommit(true);
JOptionPane.showMessageDialog(null, "批量修改成功", "批量修改", 1);
} catch (Exception e1) {
e1.printStackTrace();
// JOptionPane.showMessageDialog(null, "批量修改失败", "批量修改", 0);
try {
// 失败则事务回滚
con.rollback();
} catch (SQLException e2) {
e2.printStackTrace();
}
}
}
});
6. 删除单个车票
删除单个车票比较简单,根据用户输入的车次名删除即可,因此选择了直接弹出对话框,用户输入即可
/**
* 删除单个信息按钮
*/
Button_deleteOne.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
try {
//弹出消息对话框,获取用户输入的信息
String inputDialog = JOptionPane.showInputDialog("删除指定车次");
if (inputDialog != null) {
String sql = "DELETE FROM tickets WHERE NAME=?";
runner.update(con, sql, inputDialog);
JOptionPane.showMessageDialog(null, "删除成功", "删除", 1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
7. 删除所有车票
考虑到涉及到数据库的两个表,【tickets表】和【person表】,因此加了一个窗口【deleteWindow】
点击按钮弹出【deleteWindow】窗口
/**
* 删除所有信息
*/
Button_deletemore.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
deleteWindow frame = new deleteWindow(con);
new Thread(frame).start();
}
});
8. 超链接
点击则用本地浏览器打开链接
// 点击打开超链接
lblNewLabel_1.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
try {
URI url = new URI("");
Desktop.getDesktop().browse(url);
} catch (Exception e) {
e.printStackTrace();
}
}
});
六、添加单个车票窗口【InsertWindow.java】
布局就是用户可以输入要添加车票的各种信息
事件监听
1.添加车票
根据输入的车票信息添加到数据库【tickets表】中
// 点击添加车票
InsetButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
// 判断信息是否输入完整
if ("".equals(text_name.getText()) || "".equals(text_start.getText()) || "".equals(text_end.getText())
|| "".equals(text_number.getText()) || "".equals(text_price.getText())) {
JOptionPane.showMessageDialog(null, "信息不完整", "Warning", 0);
} else {
try {
// 插入语句
String insert = "INSERT INTO tickets(name,start,end,price,number) VALUES(?,?,?,?,?)";
String select = "select name from tickets where name=?";
// 获取车票信息
String name = text_name.getText();
String start = text_start.getText();
String end = text_end.getText();
int number = Integer.parseInt(text_number.getText());
double price = Double.parseDouble(text_price.getText());
// 实例化QueryRunner对象,获取查询语句返回的结果,根据结果来判断车次是否存在
BeanHandler<String> bh = new BeanHandler<String>(String.class);
String getname = runner.query(con, select, bh, name);
if (getname != null) {
// 车次如果已存在则弹出消息框提示用户是否覆盖
int a = JOptionPane.showConfirmDialog(null, "车次信息插入失败,已经存在该车次,如果要继续插入则覆盖原有信息", "Warning",
JOptionPane.YES_NO_OPTION);
if (a == 0) {
String update = "UPDATE tickets SET START=?,END=?,price=?,NUMBER=? WHERE NAME=?";
runner.update(con, update, start, end, price, number, name);
JOptionPane.showMessageDialog(null, name + "车次信息已修改", "修改结果", 1);
}
} else {
// 车次不存在则插入信息
runner.update(con, insert, name, start, end, price, number);
JOptionPane.showMessageDialog(null, name + "车次信息已插入", "", 1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
七、修改单个车票窗口【updateWindow.java】
布局就是用户输入要修改车票的各种信息,
事件监听
1.修改
根据车次名称修改【tickets表】中的数据
// 点击输入修改信息
InsetButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
// 判断信息是否输入完整
if ("".equals(text_name.getText()) || "".equals(text_start.getText()) || "".equals(text_end.getText())
|| "".equals(text_number.getText()) || "".equals(text_price.getText())) {
JOptionPane.showMessageDialog(null, "信息不完整", "Warning", 0);
} else {
try {
String select = "select name from tickets where name=?";
// 获取车票信息
String name = text_name.getText();
String start = text_start.getText();
String end = text_end.getText();
int number = Integer.parseInt(text_number.getText());
double price = Double.parseDouble(text_price.getText());
// 实例化QueryRunner对象,获取查询语句返回的结果,根据结果来判断车次是否存在
BeanHandler<String> bh = new BeanHandler<String>(String.class);
String getname = runner.query(con, select, bh, name);
if (getname == null) {
// 车次如果已存在则弹出消息框提示用户是否覆盖
JOptionPane.showMessageDialog(null, "车次信息修改失败,不存在该车次,请插入信息后修改", "修改结果", 0);
} else {
// 修改语句
String update = "UPDATE tickets SET START=?,END=?,price=?,NUMBER=? WHERE NAME=?";
runner.update(con, update, start, end, price, number, name);
JOptionPane.showMessageDialog(null, name + "车次信息已修改", "修改结果", 1);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
八、删除所有车票窗口【deleteWindow.java】
清空数据库中对应的表的所有数据
事件监听
1.清空所有车票信息
删除数据库【tickets表】中的所有数据
btnNewButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
try {
int a = JOptionPane.showConfirmDialog(null, "是否要删除所有数据", "Warning",
JOptionPane.YES_NO_OPTION);
if(a==0) {
String sql = "delete from tickets";
runner.update(con, sql);
JOptionPane.showMessageDialog(null, "所有车票信息已删除", "删除结果", 1);
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
2.清空所有历史信息
删除数据库【person表】中的所有数据
btnNewButton_1.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
try {
int a = JOptionPane.showConfirmDialog(null, "是否要删除所有数据", "Warning",
JOptionPane.YES_NO_OPTION);
if(a==0) {
String sql = "delete from person";
runner.update(con, sql);
JOptionPane.showMessageDialog(null, "所有历史信息已删除", "删除结果", 1);
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
});
DEMO源码
Java——Demo智能火车票购票系统源码.zip