文档版本 开发工具 测试平台 工程名字 日期 作者 备注
v1.0 2016.05.11 lutianfei none
jdbcjdbc介绍jdbc是什么?
jdbc(java data base connectivity,java数据库连接)sun公司为了简化、统一对数据库的操作,定义了一套java操作数据库的规范,称之为jdbc。简单说,就是可以直接通过java语言去操作数据库。jdbc是一套标准,它是由一些接口与类组成的。
组成jdbc的类和接口java.sql
类:drivermanger接口 connection statement resultset preparedstatement callablestatement(它是用于调用存储过程)javax.sql
接口 datasource(数据源)
什么是驱动?
两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。
jdbc入门第一个jdbc程序编程从user表中读取数据,并打印在命令行窗口中。
一、搭建实验环境 :
1、在mysql中创建一个库,并创建user表和插入表的数据。2、新建一个java工程,并导入数据驱动。二、编写程序,在程序中加载数据库驱动
drivermanager. registerdriver(driver driver) 三、建立连接(connection)
connection conn = drivermanager.getconnection(url,user,pass); 四、创建用于向数据库发送sql的statement对象,并发送sql
statement st = conn.createstatement();resultset rs = st.executequery(sql);五、从代表结果集的resultset中取出数据,打印到命令行窗口六、断开与数据库的连接,并释放相关资源
create table user( id int primary key auto_increment, username varchar(20) unique not null, password varchar(20) not null, email varchar(40) not null);insert into user values(null,'tom','123','tom@163.com');insert into user values(null,'fox','123','fox@163.com');
1.加载驱动
将驱动jar包复制到lib下.2.创建一个jdbcdemo1类public static void main(string[] args) throws sqlexception { // 1.注册驱动 // drivermanager.registerdriver(new driver()); //加载了两个驱动 class.forname(com.mysql.jdbc.driver); // 加载mysql驱动 // 2.获取连接对象 connection con = drivermanager.getconnection( jdbc:mysql://localhost:3306/day17, root, abc); // 3.通过连接对象获取操作sql语句statement statement st = con.createstatement(); // 4.操作sql语句 string sql = select * from user; // 操作sql语句(select语句),会得到一个resultset结果集 resultset rs = st.executequery(sql); // 5.遍历结果集 // boolean flag = rs.next(); // 向下移动,返回值为true,代表有下一条记录. // int id = rs.getint(id); // string username=rs.getstring(username); // system.out.println(id); // system.out.println(username); while(rs.next()){ int id=rs.getint(id); string username=rs.getstring(username); string password=rs.getstring(password); string email=rs.getstring(email); system.out.println(id+ +username+ +password+ +email); } //6.释放资源 rs.close(); st.close(); con.close();}
jdbc操作详解1.注册驱动jdbc程序中的drivermanager是java.sql包下的一个驱动管理的工具类,可以理解成是一个容器(vector),可以装入很多数据库驱动,并创建与数据库的链接,这个api的常用方法:
drivermanager.registerdriver(new driver())drivermanager.getconnection(url, user, password),registdriver方法分析
public static synchronized void registerdriver(java.sql.driver driver)
参数:java.sql.driver我们传递的是 : com.mysql.jdbc.driver;在com.mysql.jdbc.driver类中有一段静态代码块:static { try { java.sql.drivermanager.registerdriver(new driver()); } catch (sqlexception e) { throw new runtimeexception(can't register driver!); }}
上述代码的问题:
1.在驱动管理器中会装入两个mysql驱动.
解决方案:使用反射 class.forname(com.mysql.jdbc.driver);分析:使用反射的方式来加载驱动有什么好处?
一、查看driver的源代码可以看到,如果采用此种方式,会导致驱动程序注册两次,也就是在内存中会有两个driver对象。二、程序依赖mysql的api,脱离mysql的jar包,程序将无法编译,将来程序切换底层数据库将会非常麻烦。2.可以通过drivermanager来获取连接对象
connection con=drivermanager.getconection(string url,string user,string password);url作用:就是用于确定使用哪一个驱动.
mysql url: jdbc: mysql ://localhsot:3306/数据库名oralce url: jdbc : oracle :thin :@ localhost :1521 :siddrivermanager作用总结:
1.注册驱动2.获取连接connection数据库urlurl用于标识数据库的位置,程序员通过url地址告诉jdbc程序连接哪个数据库,url的写法为:
jdbc : mysql : // localhost :3306/test ?key=valueurl格式
主协议 子协议 主机 端口 数据库jdbc : mysql ://localhost:3306/day17mysql的url可以简写
前提:主机是:localhost 端口是 :3306jdbc : mysql : ///day17在url后面可以带参数
eg: useunicode=true&characterencoding=utf-8
2.connection详解java.sql.connection,它代表的是一个连接对象。简单说,就是我们程序与数据库连接。
connection作用:
1.可以通过connection获取操作sql的statement对象。
statement createstatement() throws sqlexception示例:
statement st=con.createstatement();2.操作事务
setautocommit(boolean flag);开启事务,设置事务是否自动提交。 rollback();事务回滚,在此链接上回滚事务。commit();事务提交,在链接上提交事务。 —与事务相关!!了解:
1.可以获取执行预处理的preparedstatement对象.创建向数据库发送预编译sql的preparesatement对象
preparedstatement preparestatement(string sql) throws sqlexception2.可以获取执行存储过程的 callablestatement,创建执行存储过程的callablestatement对象。
callablestatement preparecall(string sql) throws sqlexception
3.statement详解java.sql.statement用于向数据库发送sql语句,执行sql语句。statement作用1.执行sql
dml : insert update delete
int executeupdate(string sql) :用于向数据库发送insert、update或delete语句
利用返回值判断非0来确定sql语句是否执行成功。dql : select
resultset executequery(string sql) : 用于向数据发送查询语句。execute(string sql):用于向数据库发送任意sql语句2.批处理操作
addbatch(string sql); 将sql语句添加到批处理executebatch(); 向数据库发送一批sql语句执行。clearbatch(); 清空批处理。
4.resultset详解java.sql.resultset它是用于封装select语句执行后查询的结果。resultset封装执行结果时,采用的类似于表格的方式。resultset 对象维护了一个指向表格数据行的游标cursor,初始的时候,游标在第一行之前,调用resultset.next() 方法,可以使游标指向具体的数据行,进而调用方法获取该行的数据。resultset常用api1.next()方法
public boolean next();用于判断是否有下一条记录。如果有返回true,并且让游标向下移动一行。如果没有返回false.2.可以通过resultset提供的getxxx()方法来获取当前游标指向的这条记录中的列数据。
常用:
getint()getstring(int index)getstring(string columnname):也可以获得int,data等类型getdate()getdouble()参数有两种
1.getint(int columnindex);2.getint(string columnname);如果列的类型不知道,可以通过下面的方法来操作
getobject(int columnindex);getobject(string columnname);常用数据类型转换表
释放资源jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是resultset, statement和connection对象。
特别是connection对象,它是非常稀有的资源,用完后必须马上释放,如果connection不能及时、正确的关闭,极易导致系统宕机。
connection的使用原则是尽量晚创建,尽量早的释放。为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。
完整版jdbc示例代码:
public static void main(string[] args) { connection con = null; statement st = null; resultset rs = null; try { // 1.注册驱动 class.forname(com.mysql.jdbc.driver); // 2.获取连接 con = drivermanager.getconnection(jdbc:mysql:///day17, root, abc); // 3.获取操作sql语句对象statement st = con.createstatement(); // 4.执行sql rs = st.executequery(select * from user); // 5.遍历结果集 while (rs.next()) { int id = rs.getint(id); string username = rs.getstring(username); string password = rs.getstring(password); string email = rs.getstring(email); system.out.println(id + + username + + password + + email); } } catch (classnotfoundexception e) { e.printstacktrace(); } catch (sqlexception e) { e.printstacktrace(); } finally { // 6.释放资源 try { if (rs != null) { rs.close(); } } catch (sqlexception e) { e.printstacktrace(); } try { if (st != null) st.close(); } catch (sqlexception e) { e.printstacktrace(); } try { if (con != null) con.close(); } catch (sqlexception e) { e.printstacktrace(); } } }}
使用jdbc对数据库进行crudjdbc中的statement对象用于向数据库发送sql语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
statement对象的executeupdate方法,用于向数据库发送增、删、改的sql语句,executeupdate执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
statement.executequery方法用于向数据库发送查询语句,executequery方法返回代表查询结果的resultset对象。
1.查询
1.查询全部2.条件查询—根据id2.修改3.删除4.添加
练习:编写程序对user表进行增删改查操作。
练习:编写工具类简化crud操作。(异常暂不处理)
jdbcutils工具类只抽取到connection//jdbc.propertiesdriverclass=com.mysql.jdbc.driverurl=jdbc:mysql:///day17username=rootpassword=abcpublic class jdbcutils { private static final string driverclass; private static final string url; private static final string username; private static final string password; static { driverclass = resourcebundle.getbundle(jdbc).getstring(driverclass); url = resourcebundle.getbundle(jdbc).getstring(url); username = resourcebundle.getbundle(jdbc).getstring(username); password = resourcebundle.getbundle(jdbc).getstring(password); } static { try { // 将加载驱动操作,放置在静态代码块中.这样就保证了只加载一次. class.forname(driverclass); } catch (classnotfoundexception e) { e.printstacktrace(); } } public static connection getconnection() throws sqlexception { // 2.获取连接 connection con = drivermanager.getconnection(url, username, password); return con; } //关闭操作 public static void closeconnection(connection con) throws sqlexception{ if(con!=null){ con.close(); } } public static void closestatement(statement st) throws sqlexception{ if(st!=null){ st.close(); } } public static void closeresultset(resultset rs) throws sqlexception{ if(rs!=null){ rs.close(); } }}
jdbc curd//jdbc的crud操作public class jdbcdemo6 { @test public void findbyidtest() { // 1.定义sql string sql = select * from user where id=1; connection con = null; statement st = null; resultset rs = null; try { // 1.注册驱动 class.forname(com.mysql.jdbc.driver); // 2.获取连接 con = drivermanager.getconnection(jdbc:mysql:///day17, root, abc); // 3.获取操作sql语句对象statement st = con.createstatement(); // 4.执行sql rs = st.executequery(sql); // 5.遍历结果集 while (rs.next()) { int id = rs.getint(id); string username = rs.getstring(username); string password = rs.getstring(password); string email = rs.getstring(email); system.out.println(id + + username + + password + + email); } } catch (classnotfoundexception e) { e.printstacktrace(); } catch (sqlexception e) { e.printstacktrace(); } finally { // 6.释放资源 try { if (rs != null) { rs.close(); } } catch (sqlexception e) { e.printstacktrace(); } try { if (st != null) st.close(); } catch (sqlexception e) { e.printstacktrace(); } try { if (con != null) con.close(); } catch (sqlexception e) { e.printstacktrace(); } } } // 添加操作 @test public void addtest() { // 定义sql string sql = insert into user values(null,'张三','123','zs@163.com'); connection con = null; statement st = null; resultset rs = null; try { // 1.注册驱动 class.forname(com.mysql.jdbc.driver); // 2.获取连接 con = drivermanager.getconnection(jdbc:mysql:///day17, root, abc); // 3.获取操作sql语句对象statement st = con.createstatement(); // 4.执行sql int row = st.executeupdate(sql); if (row != 0) { system.out.println(添加成功); } } catch (classnotfoundexception e) { e.printstacktrace(); } catch (sqlexception e) { e.printstacktrace(); } finally { // 6.释放资源 try { if (rs != null) { rs.close(); } } catch (sqlexception e) { e.printstacktrace(); } try { if (st != null) st.close(); } catch (sqlexception e) { e.printstacktrace(); } try { if (con != null) con.close(); } catch (sqlexception e) { e.printstacktrace(); } } } // update操作 @test public void updatetest() { // 将id=3的人的password修改为456 string password = 456; string sql = update user set password=' + password + ' where id=3; // 1.得到connection connection con = null; statement st = null; try { con = jdbcutils1.getconnection(); // 3.获取操作sql语句对象statement st = con.createstatement(); // 4.执行sql int row = st.executeupdate(sql); if (row != 0) { system.out.println(修改成功); } } catch (classnotfoundexception e) { e.printstacktrace(); } catch (sqlexception e) { e.printstacktrace(); } finally { // 关闭资源 try { if (st != null) st.close(); } catch (sqlexception e) { e.printstacktrace(); } try { if (con != null) con.close(); } catch (sqlexception e) { e.printstacktrace(); } } } // delete测试 @test public void deletetest() { // 将id=3的人删除 string sql = delete from user where id=2; // 1.得到connection connection con = null; statement st = null; try { con = jdbcutils.getconnection(); // 3.获取操作sql语句对象statement st = con.createstatement(); // 4.执行sql int row = st.executeupdate(sql); if (row != 0) { system.out.println(删除成功); } } catch (sqlexception e) { e.printstacktrace(); } finally { // 关闭资源 try { jdbcutils.closestatement(st); jdbcutils.closeconnection(con); } catch (sqlexception e) { e.printstacktrace(); } } }}
resultset 滚动结果集默认得到的resultset它只能向下遍历(next()),对于resultset它可以设置成是滚动的,可以向上遍历,或者直接定位到一个指定的物理行号。
设置滚动结果集的方法
在创建statement对象时,不使用createstatement();而使用带参数的createstatement(int,int)statement createstatement(int resultsettype, int resultsetconcurrency) throws sqlexception、statement stmt = conn.createstatement(resultset.type_scroll_sensitive,resultset.concur_updatable);
第一个参数值, resultsettype
resultset.type_forward_only 该常量指示光标只能向前移动的 resultset 对象的类型。resultset.type_scroll_insensitive 该常量指示可滚动但通常不受 resultset 底层数据更改影响的 resultset 对象的类型。resultset.type_scroll_sensitive 该常量指示可滚动并且通常受 resultset 底层数据更改影响的 resultset 对象的类型。第二个参数值,resultsetconcurrency
resultset.concur_read_only 该常量指示不可以更新的 resultset 对象的并发模式。resultset.concur_updatable 该常量指示可以更新的 resultset 对象的并发模式。以上五个值,可以有三种搭配方式
resultset.type_forward_only resultset.concur_read_only 默认,不受底层影响resultset.type_scroll_insensitive resultset.concur_read_only resultset.type_scroll_sensitive resultset.concur_updatable 滚动的,可以并发更新的常用api
next():移动到下一行previous():移动到前一行absolute(int row):移动到指定行beforefirst():移动resultset的最前面afterlast() :移动到resultset的最后面updaterow() :更新行数据
dao模式——javaee模式dao模式(data access object 数据访问对象):在持久层通过dao将数据源操作完全封装起来,业务层通过操作java对象,完成对数据源操作业务层无需知道数据源底层实现 ,通过java对象操作数据源
dao模式结构1、datasource数据源(mysql数据库)2、business object 业务层代码,调用dao完成 对数据源操作 (代表数据的使用者)3、dataaccessobject 数据访问对象,持久层dao程序,封装对数据源增删改查,提供方法参数都是java对象4、transferobject 传输对象(值对象) 业务层通过向数据层传递 to对象,完成对数据源的增删改查(表示数据的java bean)
使用dao模式完成登录操作需求:
1、把文件换成数据库2、使用dao模式3、防范sql注入攻击1.web层
login.jsp loginservlet user2.service层
userservice(实际应是接口)3.dao层
userdao(实际应是接口)
具体代码见工程day17_2。
用户注册流程
sql注入由于没有对用户输入进行充分检查,而sql又是拼接而成,在用户输入参数时,在参数中添加一些sql 关键字,达到改变sql运行结果的目的,也可以完成恶意攻击。1、statement存在sql注入攻击问题
例如登陆用户名采用 xxx’ or ‘1’=‘1使用mysql注释2、对于防范 sql 注入,可以采用preparedstatement取代statement。
它是一个预处理的statement,它是java.sql.statement接口的一个子接口。preparedstatement是statement的子接口,它的实例对象可以通过调connection.preparedstatement(sql)方法获得statement会使数据库频繁编译sql,可能造成数据库缓冲区溢出。preparedstatement 可对sql进行预编译,从而提高数据库的执行效率。preperedstatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。preparedstatement使用总结
1.在sql语句中,使用?占位
string sql=”select * from user where username=? and password=?”;2.得到preparedstatement对象
preparedstatement pst=con.preparestatement(string sql);3.对占位符赋值
pst.setxxx(int index,xxx obj);例如:
setint()setstring();参数index,代表的是”?“的序号.注意:从1开始。4.执行sql
dml: pst.executeupdate();dql: pst.executequery();注意:这两方法无参数关于preparedstatement优点:
1.解决sql注入(具有预处理功能)2.不需要再拼sql语句。
jdbc处理大数据在实际开发中,程序需要把大文本 text 或二进制数据 blob保存到数据库。
text是mysql叫法,oracle中叫clob 大数据也称之为lob(large objects),lob又分为:
clob用于存储大文本。textblob用于存储二进制数据,例如图像、声音、二进制文等。text和blob分别又分为:
text(clob)
tinytext(255b)、text(64kb)、mediumtext(16m)和longtext(4g)blob
tinyblob(255b)、blob(64kb)、mediumblob(16m)和longblob(4g)对于大数据操作,我们一般只有两种: insert select
演示1: 大二进制操作
create table myblob(id int primary key auto_increment,content longblob)
public class myblobtest { // 添加 @test public void save() throws sqlexception, ioexception { string sql = insert into myblob values(null,?); // 1.获取connection connection con = jdbcutils.getconnection(); // 2.获取preparedstatement preparedstatement pst = con.preparestatement(sql); // 3.插入值 file file = new file(d:\\java1110\\day17-jdbc\\视频\\3.jdbc快速入门.avi); fileinputstream fis = new fileinputstream(file); pst.setbinarystream(1, fis, (int) (file.length())); //mysql驱动只支持最后一个参数为int类型的方法 int row = pst.executeupdate(); if (row != 0) { system.out.println(插入成功); } // 4.释放资源 fis.close(); pst.close(); con.close(); } // 获取 @test public void get() throws sqlexception, ioexception { string sql = select * from myblob where id=?; // 1.获取connection connection con = jdbcutils.getconnection(); // 2.获取preparedstatement preparedstatement pst = con.preparestatement(sql); pst.setint(1, 1); // 3.得到结果集 resultset rs = pst.executequery(); // 4.遍历结果集 if (rs.next()) { // system.out.println(rs.getint(id)); inputstream is = rs.getbinarystream(content);// 得到的这个输入流它的源可以理解成就是数据库中的大二进制信息 fileoutputstream fos = new fileoutputstream(d:/a.avi); int len = -1; byte[] b = new byte[1024 * 100]; while ((len = is.read(b)) != -1) { fos.write(b, 0, len); fos.flush(); } fos.close(); is.close(); } // 5.关闭 rs.close(); pst.close(); con.close(); }}
向表中插入数据可能出现的问题
问题1:java.lang.abstractmethoderror: com.mysql.jdbc.preparedstatement.setbinarystream(iljava/io/inputstream;)
原因:mysql驱动不支持setbinarystream(int,inputstream);
修改成 pst.setbinarystream(1, fis,file.length());
原因:因为mysql驱动不支 setbinarystream(int,inputstream,long);
解决: mysql驱动支持setbinarystream(int,inputstream,int);
注意:如果文件比较大,那么需要在my.ini文件中配置
max_allowed_packet=64m总结:
存:pst.setbinarystream(1, fis, (int) (file.length()));取:inputstream is = rs.getbinarystream(“content”);
使用jdbc处理大文本对于mysql中的text类型,可调用如下方法设置:preparedstatement.setcharacterstream(index, reader, length);//注意length长度须设置,并且设置为int型//当包过大时修改配置:[mysqld] max_allowed_packet=64m
对mysql中的text类型,可调用如下方法获取:reader = resultset. getcharacterstream(i);等价于reader = resultset.getclob(i).getcharacterstream();
演示:存储大文本create table mytext(id int primary key auto_increment,content longtext)//存储file file = new file(d:\\java1110\\workspace\\day17_3\\a.txt);filereader fr = new filereader(file);pst.setcharacterstream(1, fr, (int) (file.length()));//获取:reader r = rs.getcharacterstream(content);
使用jdbc处理二进制数据对于mysql中的blob类型,可调用如下方法设置:
preparedstatement. setbinarystream(i, inputstream, length);对mysql中的blob类型,可调用如下方法获取:
inputstream in = resultset.getbinarystream(i);inputstream in = resultset.getblob(i).getbinarystream(); public class mytexttest { // 存储 @test public void save() throws sqlexception, filenotfoundexception { string sql = insert into mytext values(null,?); // 1.获取connection connection con = jdbcutils.getconnection(); // 2.获取preparedstatement preparedstatement pst = con.preparestatement(sql); // 3.插入值 file file = new file(d:\\java1110\\workspace\\day17_3\\a.txt); filereader fr = new filereader(file); pst.setcharacterstream(1, fr, (int) (file.length())); pst.executeupdate(); // 4.释放资源 pst.close(); con.close(); } // 获取 @test public void get() throws sqlexception, ioexception { string sql = select * from mytext where id=?; // 1.获取connection connection con = jdbcutils.getconnection(); // 2.获取preparedstatement preparedstatement pst = con.preparestatement(sql); pst.setint(1, 1); // 3.得到结果集 resultset rs = pst.executequery(); // 4.遍历结果集 if (rs.next()) { reader r = rs.getcharacterstream(content); filewriter fw = new filewriter(d:/笔记.txt); int len = -1; char[] ch = new char[1024 * 100]; while ((len = r.read(ch)) != -1) { fw.write(ch, 0, len); fw.flush(); } fw.close(); r.close(); } pst.close(); con.close(); }}
jdbc批处理业务场景:当需要向数据库发送一批sql语句执行时,应避免向数据库一条条的发送执行,而应采用jdbc的批处理机制,以提升执行效率。
实现批处理有两种方式,第一种方式:
statement.addbatch(sql) executebatch()方法:执行批处理命令clearbatch()方法:清除批处理命令采用statement.addbatch(sql)方式实现批处理:
优点:可以向数据库发送多条不同的sql语句。缺点:
sql语句没有预编译。当向数据库发送多条语句相同,但仅参数不同的sql语句时,需重复写上很多条sql语句。例如:
insert into user(name,password) values(‘aa’,’111’);insert into user(name,password) values(‘bb’,’222’);insert into user(name,password) values(‘cc’,’333’);insert into user(name,password) values(‘dd’,’444’);实现批处理的第二种方式
preparedstatement.addbatch()
addbatch();executebatch();clearbatch();采用preparedstatement.addbatch()实现批处理
优点:发送的是预编译后的sql语句,执行效率高。缺点:只能应用在sql语句相同,但参数不同的批处理中。因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据。两个对象执行批处理区别?
1.statement它更适合执行不同sql的批处理。它没有提供预处理功能,性能比较低。2.preparedstatement它适合执行相同sql的批处理,它提供了预处理功能,性能比较高。
eg:第一种方式connection conn = null;statement st = null;resultset rs = null;try {conn = jdbcutil.getconnection();string sql1 = insert into person(name,password,email,birthday) values('kkk','123','abc@sina.com','1978-08-08');string sql2 = update user set password='123456' where id=3;st = conn.createstatement();st.addbatch(sql1); //把sql语句加入到批命令中st.addbatch(sql2); //把sql语句加入到批命令中st.executebatch();} finally{ jdbcutil.free(conn, st, rs);}
eg:第二种方式conn = jdbcutil.getconnection();string sql = insert into person(name,password,email,birthday) values(?,?,?,?);st = conn.preparestatement(sql);for(int i=0;i<50000;i++){st.setstring(1, aaa + i);st.setstring(2, 123 + i);st.setstring(3, aaa + i + @sina.com);st.setdate(4,new date(1980, 10, 10));st.addbatch(); if(i%1000==0){st.executebatch();st.clearbatch();}}st.executebatch();
注意;mysql默认情况下,批处理中的预处理功能没有开启,需要开启
1.在 url下添加参数
url=jdbc :mysql :///day17?useserverprepstmts=true&cacheprepstmts=true&rewritebatchedstatements=true2.注意驱动版本
mysql驱动要使用mysql-connector-java-5.1.13以上作业:1.注册+登录案例采用dao模式 使用preparedstatement操作
2.使用preparedstatement完成crud
客户信息表dao编写
创立如下数据库表customer,并编写dao进行crud操作
