什么是jdbc
jdbc(java database connectivity),即java数据库连接,是一种用于执行sql语句的java api,可以为多种关系数据库提供同一访问,它由一组用java语言编写的类和接口组成。jdbc提供了一种基准,根据这种基准可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。总而言之,jdbc做了三件事:
1、与数据库建立连接
2、发送操作数据库的语句
3、处理结果
jdbc简单示例
下面的代码演示了如何利用jdbc从数据库中查询若干条符合要求的数据出来,使用的数据库是mysql。
1、建立一个数据库和一张表,我的习惯是在classpath底下建立一个.sql的文件用于存放sql语句
create database school;
use school;
create table student
(
studentid int primary key auto_increment not null,
studentname varchar(10) not null,
studentage int,
studentphone varchar(15)
)
insert into student values(null,‘betty’, ‘20’, ‘00000000’);
insert into student values(null,‘jerry’, ‘18’, ‘11111111’);
insert into student values(null,‘betty’, ‘21’, ‘22222222’);
insert into student values(null,‘steve’, ‘27’, ‘33333333’);
insert into student values(null,‘james’, ‘22’, ‘44444444’);
commit;
2、建立一个.properties文件用于存储mysql连接的几个属性。为什么要建立.properties而不在代码里面写死,由于这个并不是java设计模式的分类,就不细讲了,只需要记住:从设计的角度看,把内容写在配置文件中永远好过把内容写死在代码中。
mysqlpackage=com.mysql.jdbc.driver
mysqlurl=jdbc:mysql://localhost:3306/school?useunicode=true&characterencoding=utf-8
mysqlname=root
mysqlpassword=root
3、根据表字段建立实体类
public class student
{
private int studentid;
private string studentname;
private int studentage;
private string studentphone;
public student(int studentid, string studentname, int studentage,
string studentphone)
{
this.studentid = studentid;
this.studentname = studentname;
this.studentage = studentage;
this.studentphone = studentphone;
}
public int getstudentid()
{
return studentid;
}
public string getstudentname()
{
return studentname;
}
public int getstudentage()
{
return studentage;
}
public string getstudentphone()
{
return studentphone;
}
public string tostring()
{
return “studentid = ” + studentid + “, studentname = ” + studentname + “, studentage = ” +
studentage + “, studentphone = ” + studentphone;
}
}
4、写一个dbconnection类专门用于向外提供数据库连接。我这里用了mysql,所以只有一个mysqlconnection,如果还用到了oracle,当然还可以向外提供一个oracleconnection。把这些连接设为全局的可能有人会想是否会有线程安全问题,这是一个很好的问题。那因为我们只从connection里面读取一个preparedstatement出来,而不会去写它,只读不修改,是不会引发线程安全问题的。另外把connection设置为static的保证了connection在内存中只有一份,不会占多大资源,每次使用完不调用close()方法去关闭它也没事。
public class dbconnection
{
private static properties properties = new properties();
static
{
/** 要从classpath下取.properties文件,因此要加“/” */
inputstream is = dbconnection.class.getresourceasstream(“/db.properties”);
try
{
properties.load(is);
}
catch (ioexception e)
{
e.printstacktrace();
}
}
/** 这个mysqlconnection只是为了用来从里面读一个preparedstatement,不会往里面写数据,因此没有线程安全问题,可以作为一个全局变量 */
public static connection mysqlconnection = getconnection();
public static connection getconnection()
{
connection con = null;
try
{
class.forname((string)properties.getproperty(“mysqlpackage”));
con = drivermanager.getconnection((string)properties.getproperty(“mysqlurl”),
(string)properties.getproperty(“mysqlname”),
(string)properties.getproperty(“mysqlpassword”));
}
catch (classnotfoundexception e)
{
e.printstacktrace();
}
catch (sqlexception e)
{
e.printstacktrace();
}
return con;
}
}
5、建立一个工具类,用来写各种方法,专门和数据库进行交互。这种工具类最好搞成单例的,这样就不用每次去new出来了(实际上new出来也没看出来会有什么好处),节省资源
package com.xrq.test11;
import java.sql.connection;
import java.sql.preparedstatement;
import java.sql.resultset;
import java.util.arraylist;
import java.util.list;
public class studentmanager
{
private static studentmanager instance = new studentmanager();
private studentmanager()
{
}
public static studentmanager getinstance()
{
return instance;
}
public list querysomestudents(string studentname) throws exception
{
list studentlist = new arraylist();
connection connection = dbconnection.mysqlconnection;
preparedstatement ps = connection.preparestatement(“select * from student where studentname = ?”);
ps.setstring(1, studentname);
resultset rs = ps.executequery();
student student = null;
while (rs.next())
{
student = new student(rs.getint(1), rs.getstring(2), rs.getint(3), rs.getstring(4));
studentlist.add(student);
}
ps.close();
rs.close();
return studentlist;
}
}
6、写个main函数去调用一下
list studentlist = new arraylist《student>();
studentlist = studentmanager.getinstance().querysomestudents(“betty”);
for (student student : studentlist)
system.out.println(student);
7、看一下运行结果,和数据库里面的一样,成功
studentid = 1, studentname = betty, studentage = 20, studentphone = 00000000
studentid = 3, studentname = betty, studentage = 21, studentphone = 22222222
#p#
为什么要使用占位符“?”
#e#
为什么要使用占位符“?”
看一下第5点,大家一定注意到了,写sql语句的时候用了“?”占位符,当然有美化代码的因素,不用占位符就要在括号里写“+”来拼接参数,如果要拼接的参数一多,代码肯定不好看,可读性不强。但是除了这个原因,还有另外一个重要的原因,就是避免一个安全问题。假设我们不用占位符写sql语句,那“querysomestudents(string name) throws exception”方法就要这么写:
public list querysomestudents(string studentname) throws exception
{
list studentlist = new arraylist();
connection connection = dbconnection.mysqlconnection;
preparedstatement ps = connection.preparestatement(“select * from student where studentname = ‘” + studentname + “’”);
resultset rs = ps.executequery();
student student = null;
while (rs.next())
{
student = new student(rs.getint(1), rs.getstring(2), rs.getint(3), rs.getstring(4));
studentlist.add(student);
}
ps.close();
rs.close();
return studentlist;
}
上面的main函数一样可以获取到两条数据,但是问题来了,如果我这么调用呢:
public static void main(string[] args) throws exception
{
list studentlist = new arraylist《student>();
studentlist = studentmanager.getinstance().querysomestudents(“‘ or ’1‘ = ’1”);
for (student student : studentlist)
system.out.println(student);
}
看下运行结果:
studentid = 1, studentname = betty, studentage = 20, studentphone = 00000000
studentid = 2, studentname = jerry, studentage = 18, studentphone = 11111111
studentid = 3, studentname = betty, studentage = 21, studentphone = 22222222
studentid = 4, studentname = steve, studentage = 27, studentphone = 33333333
studentid = 5, studentname = james, studentage = 22, studentphone = 44444444
为什么?看下拼接之后的sql语句就知道了:
select * from student where studentname = ‘’ or ‘1’ = ‘1’‘1’=‘1’永远成立,所以前面的查询条件是什么都没用。这种问题是有应用场景的,不是随便写一下。java越来越多的用在web上,既然是web,那么查询的时候有一种情况就是用户输入一个条件,后台获取到查询条件,拼接sql语句查数据库,有经验的用户完全可以输入一个“‘‘’ or ‘1’ = ‘1”,这样就拿到了库里面的所有数据了。
jdbc事物
谈数据库必然离不开事物,事物简单说就是“要么一起成功,要么一起失败”。那简单往前面的studentmanager里面写一个插入学生信息的方法:
public void addstudent(string studentname, int studentage, string studentphone) throws exception
{
connection connection = dbconnection.mysqlconnection;
preparedstatement ps = connection.preparestatement(“insert into student values(null,?,?,?)”);
ps.setstring(1, studentname);
ps.setint(2, studentage);
ps.setstring(3, studentphone);
if (ps.executeupdate() > 0)
system.out.println(“添加学生信息成功”);
else
system.out.println(“添加学生信息失败”);
}
public static void main(string[] args) throws exception
{
studentmanager.getinstance().addstudent(“betty”, 17, “55555555”);
}
运行就不运行了,反正最后结果是“添加学生信息成功”,数据库里面多了一条数据。注意一下:
1、增删改用的是executeupdate()方法,因为增删改认为都是对数据库的更新
2、查询用的是executequery()方法,看名字就知道了“query”,查询嘛
可能有人注意到一个问题,就是java代码在insert后并没有对事物进行commit,数据就添加进数据库了,也能查出来,这是为什么呢?因为jdk的connection设置了事物的自动提交。如果在addstudent(。..)方法里面这么写:
connection connection = dbconnection.mysqlconnection;
connection.setautocommit(false);
autocommit这个属性原来是true,jdk自然会帮助开发者自动提交事物了。ok,如果要改成手动提交事物的代码,那么应该这么写addstudent(。..)方法:
public void addstudent(string studentname, int studentage, string studentphone) throws exception
{
connection connection = dbconnection.mysqlconnection;
connection.setautocommit(false);
preparedstatement ps = connection.preparestatement(“insert into student values(null,?,?,?)”);
ps.setstring(1, studentname);
ps.setint(2, studentage);
ps.setstring(3, studentphone);
try
{
ps.executeupdate();
connection.commit();
}
catch (exception e)
{
e.printstacktrace();
connection.rollback();
}
}
要记得抛异常的时候利用rollback()方法回滚掉事物。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助。
从2018深圳高交会看LED屏行业发展趋势
NASA帕克探测器怎么解开太阳活动谜团
TUV莱茵举办"摩托车头盔和PPE头盔护具出口认证要求解读"研讨会
联邦快递宣称被失误转运 华为正式提起诉讼
5G助力管理智能化_应用又添新场景
详解JDBC使用
2020优秀的降噪耳机推荐!主动降噪蓝牙耳机排行
keil5+STM32F103C8T6设计的智能插座+人体感应灯 支持跨平台编译运行
小米的无人机有6大问题最值得关注
IIC-China 2010电子元器件参展商展前专访:市港源
智核助力 软通动力Rglam(安歌)引领机器人客服市场
艺术家使用NVIDIA Omniverse创造出照明效果逼真的3D模型
如何创建一款您的车载充电器?
Matter认证: 为物联网设备所带来的价值
特朗普气炸了!华为居然还能通过开源获取美国技术
使用氨气检测仪的原因是什么
macOS和Linux的内核之间的区别详解
场效应管与igbt管区别 怎样区分场效应管与IGBT管
厦门易派电子科技毫米波雷达感应人体存在控制灯光亮灭,为何比红外技术更适用
SA4828管脚图