学习了java的可视化控件还有数据库,我们可以写一个简单的可以实现增删改查的界面,界面效果大概如下(界面不太美观,过几天我会写一个JavaWeb项目来在浏览器上实现此功能,今天写下此博客来记录一下遇到的问题和解决方法)以下可以直接跳转到您想看的位置,点击跳转 ↓↓↓ :
- 连接数据库必备jar包及使用方法
- 软件的简单介绍
- 问题及解决方法
- 软件的运行示例
- 神奇的源代码详解
😵代码写的不太好,欢迎大家指出不足之处.o( ̄▽ ̄)ブ
- 先放一张截图:
显然我们可以看到此软件的布局和功能:
- 布局:
- 整体的面板采用的是BorderLayout布局方式:
窗口大小不可以调整,但是窗口每次更新数据后会自动调整窗口的高度,来满足更多的数据能够输出到窗口中.
在整体布局的上面(“North”)部分是一个独立的画板,来显示数据库表格中的所有数据,并按照一定格式显示出来,不可被编辑.
在整体布局的Center部分也是独立的画板,只用来显示提示用户输入的信息.
在布局的South(底部),添加了两行,如图中所示,一行是输入框一行是功能按钮.在右下角还有一个提示框,用来提示用户正确操作.
修改操作没有添加,因为这几个输入框不能完全满足所有功能,修改功能也可以先删除再添加,效果一样。
- 功能:
如大家所见,实现了增删查的功能,至于改的操作,需要单独的界面,就暂时没有写.可以通过先删除,后增加的方式一样可以实现.
- 在添加时候:
-输入数据不能为空,为空有报错机制,会提示用户;
-添加的信息中学号不能重复,右下角也会给出提示
-输入数据格式要正确,学号和年龄都用的整型变量来存储,在输入的时候添加了代码的限制,只能将数字输入. - 删除的时候:
-用户根据学号来删除,不重复,防止误删;
-输入为空会提示 - 查询时候:
-用户一次只能根据一条信息来查询(学号\姓名\年龄等均可,但是只能输入一项)
-不输入或者输入多项会提示用户.
- jar包地址(百度网盘)
MySQ的jar包点我!提取码:v5sd
SQL server的点我!提取码:ra6f - 使用方法:(具体方法请看源代码)
1.在JavaWeb项目中:
直接复制到下面路径就可以(项目WEB-INF目录下的lib文件夹中,就可以使用了)
- 在java项目中使用jar包(本次使用):
首先我们找到jar包的地址,然后在环境变量中将路径添加在CLASSPATH里面(注意分号结尾不加分号):
- 现在我们就可以连接数据库了。
- 在设计的过程中遇到了几个问题
- 首先便是jar包的导入了,上面已经提到
- 其次就是关于在插入数据时侯,中文乱码问题的解决:
这里我用的是Navicat,连接的是MySQL数据库,解决方法很简单,将useUnicode=true&characterEncoding=utf8";添加到URL地址就好(具体请看代码):
"jdbc:mysql://localhost:3306/name?useUnicode=true&characterEncoding=utf8";
- 浪费时间挺长的一项: 空指针异常!
特别是在传递数据的时候,添加按钮监听器之后,取出用户输入的数据,然后再将数据输出或者转换成SQL语句.特别是在写查询语句的时候,因为查询的结果要输出,保存在字符串数组中,数组没有设定为static类型,导致一直报空指针异常的错误.卡在这好久.改成static类型的数组来存储数据就解决了. - 关于转义字符:
这个倒是很容易想到,不过还是错了一次,转义字符,比如:
String sql_1 = "insert into hello values(" + sno +",\'"+ sname +"\',\'" +ssex
+"\'," + sage + ",\'" + sdept + "\')";
我们来看运行效果:
添加成功后会自动跳出一个新窗口来更新数据:
如果学号重复,会提示:
如果输入不合规也有报错:
在删除时候,若输入的学号不存在:
如果查询时候输入多项信息:
查询成功后,会跳出一个新窗口来重新输出查询的结果.
- 源代码详解如下(一切尽在注释之中):
我们在此将数据库连接代码和处理数据代码分开,结构如下:
其中,DBConnect.java显然是连接数据库的文件:
数据库连接很简单,分三步来就可以
- 导入驱动
- 连接数据库
- 提交查询语句
本文件很简单,具体代码如下:
import java.beans.Statement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBConnect {
private static String DRIVER = "com.mysql.jdbc.Driver";//注意不同的数据库此项不同,可百度到相应的语句.
private static String URL = "jdbc:mysql://localhost:3306/usertest?useUnicode=true&characterEncoding=utf8";//在后面加的useUnicode=true&characterEncoding=utf8使数据库能够识别中文字符,解决乱码问题.
private static String USERNAME = "your_username";//数据库用户名
private static String PASSWORD = "your_password";//数据库密码
private static Connection connection = null;
@SuppressWarnings("rawtypes")
Statement statement = null; //状态
ResultSet result= null; //结果集
static {
try {
// 导入驱动,加载具体的驱动类
Class.forName(DRIVER);
System.out.println("连接数据库中...");
}catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
try {
connection = (Connection) DriverManager.getConnection(URL , USERNAME , PASSWORD);
System.out.println("数据库连接成功!");
}catch(SQLException e) {
System.out.println("数据库连接失败!");
e.printStackTrace();
}
return (Connection) connection;
}
下面来看主要的代码,首先我们来看查询的方法(解释都在注释中):
public void select_s(String sql_1) {
//在这里我们传过来一个参数sql_1;我们会将sql_1初始化为" ",我们调用此方法是时候,会传来一个要进行上传运行的sql语句,或者传过来" "则代表没有语句要执行.下面有判断机制:
DBConnect dbConnect = new DBConnect(); //首先我们导入DBConnect类来连接数据库
Connection connection = (Connection) dbConnect.getConnection();
Statement statement = null;
/*我们在此选择的是Statement也可以用PreparedStatement,
StatemenI和PreparedStatement都可以用于把sq1语句从java程序中发送到指定数据库,并执行sq1语句;
若:直接使用Statement,驱动程序一般不会对sql语句作处理而直接交给数据库;
使用PreparedStament,形成预编译的过程,并且会对语句作字集的转换.
所以一般使用PreparedStament效率会更高一点;
*/
try {
statement = (Statement) connection.createStatement();
}catch(SQLException e) {
e.printStackTrace();
}
ResultSet resultSet = null;
if(sql_1 != " ") {
//如果sql_1中的字符串是查询语句
try {
statement.executeUpdate(sql_1);//进行上传SQL语句的处理
} catch (SQLException e) {
e.printStackTrace();
}
}
String sql = "select * from hello where Sno > 0"; //查询出所有的数据的语句
try {
resultSet = statement.executeQuery(sql);//保存在结果集中
}catch(SQLException e) {
e.printStackTrace();
}
try
{
while(resultSet.next())
{
int Sno = resultSet.getInt("Sno");
String name = resultSet.getString("Sname");
String Ssex = resultSet.getString("Ssex");
String Sdept = resultSet.getString("Sdept");
int Sage = resultSet.getInt("Sage");
student_number[i] = Sno;//将学号存入数组,并且固定格式
date_string[i++] = "学号:" + Sno + ",姓名:" +name + ",性别:" +
Ssex + ",年龄:" + Sage + "岁,专业:" + Sdept;
//用到了变量i,i的大小就是数据库中数据的数目,我们用它来调节窗口,输出数据.
}
resultSet.close();
}catch(SQLException q)
{
q.printStackTrace();
}finally {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
- 下面是图形界面的设计和监听器的使用:
public Change() {
String sql_q = " "; //我们要调用上面的方法来获取数据,先输出所有的数据到窗口,所以初始化方法的参数
select_s(sql_q);
setTitle("数据库作业");
this.setBackground(Color.LIGHT_GRAY);
this.setLocation(500, 300); //设置窗口出现位置
this.setSize(400, 45*i); //自动随数据数目增多高度变大,排版较好
this.setResizable(false); //不可以调整窗口大小
/*然后添加一个画板,来设计第一部分(输出数据的部分)
容易发现,我在此处新建了两个画板,
因为我们正常输出需要一个
而我们的查询语句查询的结果输出也需要一个画板
所以在此设置两个画板,通过查询语句结果集中数据的个数K的值来
决定用哪一个输出.
*/
JPanel date1 = new JPanel();
date1.setLayout(new GridLayout(k + 1, 1, 1, 1)); //这是查询语句对应的画板
JPanel date = new JPanel();
date.setLayout(new GridLayout(i + 1, 1, 1, 1));//这是输出全部数据用到的画板
if(k > 0) {
for(int l = 0 ; l < k ; l++) {
text3[l] = new JTextField(date_string2[l]); //如果查询语句对应的结果个数不为0就输出,且每次输出之后都会重置k的值,所以不用担心.
text3[l].setEditable(false);
}
for(int j = 0 ; j < k; j++) {
date1.add(text3[j]);//刚才new了结果集文本框数组,我们循环将它们添加到画板
}
}else {
for(int j = 0 ; j < i; j++) {
text[j] = new JTextField(date_string[j]);
text[j].setEditable(false);//同理
}
for(int j = 0 ; j < i; j++) {
date.add(text[j]);
}
}
/*接下来是添加的另一个面板(提示用户输入的对应信息的画板,
这里我用的JButton,当然也可以用JTextField.*/
JPanel use = new JPanel();
use.setLayout(new GridLayout(1,1 , 6 ,0));
for(int j = 0 ; j < text_name.length ; j++) {
text2[j] = new JButton(text_name[j]);
//我们在上面已经准备好了字符串数组,将提示内容循环导入就好
//先创建按钮,再导入画板
}
f