企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## Java操作数据库--以SQL Server为例 ### crud介绍(增、删、改、查操作) CRUD是指在做计算处理时的增加(Create)、查询(Retrieve)(重新得到数据)、更新(Update)和删除(Delete)几个单记事的首字母简写。主要被用在描述软件系统中数据库或者持久层的基本操作功能。   ### crud介绍 要对数据表进行增、删、改、查,首先要清楚jdbc基本的概念: ![](https://box.kancloud.cn/2016-02-25_56ceb3e300512.jpg) ![](https://box.kancloud.cn/2016-02-25_56ceb3e32bacc.jpg)     JDBC有两种,一种原sun公司提供的数据库连接api但不是直接连接sql server而是先连接ODBC再通过ODBC对sql server进行操作;一种是由微软提供的JDBC数据库连接api可直接对sql server数据库进行操作。     JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序,同时,JDBC也是个商标名。     有了JDBC,向各种关系数据发送SQL语句就是一件很容易的事。换言之,有了JDBC API,就不必为访问Sybase数据库专门写一个程序,为访问Oracle数据库又专门写一个程序,或为访问Informix数据库又编写另一个程序等等,程序员只需用JDBC API写一个程序就够了,它可向相应数据库发送SQL调用。同时,将Java语言和JDBC结合起来使程序员不必为不同的平台编写不同的应用程序,只须写一遍程序就可以让它在任何平台上运行,这也是Java语言“编写一次,处处运行”的优势。 注:JDBC访问不同的数据库使用的JDBC API都有所不同,虽然统称为JDBC。如:访问sql server数据库的JDBC,是不能访问oracle数据库的,同理也是也不访问mysql、db2、Informix数据库等。只是访问方式不同,对数据库的操作依然是使用sql语句操作。     ### jdbc的驱动的分类 目前比较常见的JDBC驱动程序可分为以下四个种类 1、jdbc-odbc桥连接 2、本地协议纯java驱动程序 3、网络协议纯java驱动程序 4、本地api   ### jdbc不足 尽管JDBC在JAVA语言层面实现了统一,但不同数据库仍旧有许多差异。为了更好地实现跨数据库操作,于是诞生了Hibernate项目,Hibernate是对JDBC的再封装,实现了对数据库操作更宽泛的统一和更好的可移植性。     ### jdbc-odbc桥连的方式来操作sql server数据库 **PS:SQL文件可以到我写的上一篇博客“Java数据库基础”中找到。** ~~~ /** * 使用JDBC-ODBC桥连方式操作数据库 db中的emp,dept表 * 1.配置数据源 * 2.在程序中连接数据源 */ package com.db; import java.sql.*; public class db1 { public static void main(String[] args) { Connection ct = null; Statement sm = null; ResultSet rs = null; try { //1.加载驱动(把需要的驱动程序加入内存) Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //2.得到连接(指定连接哪个数据源,用户和密码) //配置数据源时,选择Windows NT验证,则不需要账号密码 ct = DriverManager.getConnection("jdbc:odbc:mytest"); //3.创建Statement或者PreparedStatement //Statement用处是:发送sql语句到数据库 sm = ct.createStatement(); //4.执行(crud,创建数据库,备份数据库,删除数据库。。。) //添加一条数据到dept表 //executeUpdate可以执行 cud操作(添加,删除,修改) // String sql = "insert into dept values(50, '保安部', '北京')"; // int res = sm.executeUpdate(sql); // if(res == 1){ // System.out.println("加入一条语句"); // } else { // System.out.println("添加失败"); // } //从dept删除一条记录 // String sql = "delete from dept where deptno='50'"; // int res = sm.executeUpdate(sql); // // if(res == 1){ // System.out.println("delete."); // } else { // System.out.println("failure"); // } //修改deptno=40的loc改为beijing // String sql = "update dept set loc = 'beijing' where deptno='40'"; // int res = sm.executeUpdate(sql); // if(res == 1){ // System.out.println("update."); // } else { // System.out.println("failure"); // } //显示所有的部门 //ResultSet结果集 String sql = "select * from dept"; rs = sm.executeQuery(sql); //rs指向结果集的第一行的前一行 while(rs.next()){ //取出第一行 int deptno = rs.getInt(1); String dname = rs.getString(2); String loc = rs.getString(3); System.out.println(deptno + " " + dname + " " + loc); } } catch (Exception e) { e.printStackTrace(); } finally { //关闭资源 //谁后创建,谁先关闭 try { if(rs != null){ rs.close(); } if(sm != null){ sm.close(); } if(ct != null){ ct.close(); } } catch (Exception e2) { e2.printStackTrace(); } } } } ~~~     ### Statement和PreparedStatement的区别(1)     Statemen和PreparedStatement都可以用于把sql语句从java程序中发送到指定数据库,并执行sql语句,但是他们也存在区别: 1、直接使用Statement,驱动程序一般不会对sql语句作处理而直接交给数据库;使用PreparedStatement,形成预编译的过程,并且会对语句作字符集的转换(至少在sql server)中如此。     如此,有两个好处:对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch;另外,可以比较好地解决系统的本地化问题。 2、PreparedStatement还能有效的防止危险字符的注入,也就是sql注入的问题。   ### Statement和PreparedStatement的区别(2) 看下面两段程序片断: Code Fragment 1: ~~~ String updateString="UPDATE COFFEES SET SALES=75"+"WHERE COF_NAME LIKE 'Colombian'"; stmt.executeUpdate(updateString); ~~~ Code Fragment 2: ~~~ PreparedStatement updateSales=con.prepareStatement("UPDATE COFFEES SET SALES=? WHERE COF_NAME LIKE ?"); updateSales.setInt(1,75); updateSales.setString(2,"Colombian"); updateSales.executeUpdate(); ~~~     后者使用了PreparedStatement,而前者是Statement,PreparedStatement不仅包含了SQL语句,而且大多数情况下这个语句已被预编译过,当其执行时,只需DBMS运行SQL语句,而不必先编译。当你需要执行Statement对象多次的时候,PreparedStatement对象将会降低运行时间,加快了访问数据库的速度。     好处是,不必重复SQL语句的句法,而只需要改其中变量的值,便可重新执行SQL语句。选择PreparedStatement对象与否,在于相同句法的SQL语句是否执行了多次,而且两次之间的差别仅是变量的不同。如仅执行一次的话,它和普通的对象无差异,体现不出预编译的优越性。 ~~~ /** * PreparedStatement使用CRUD * 1.PreparedStatement 可以提高执行效率(因为有预编译功能) * 2.PreparedStatement 可以防止sql注入,但是要用?赋值的方式 */ package com.db; import java.sql.*; public class db2 { public static void main(String[] args) { //定义对象 PreparedStatement ps = null; Connection ct = null; ResultSet rs = null; try { //加载驱动 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //得到连接 ct = DriverManager.getConnection("jdbc:odbc:mytest"); // //查询 // //创建PreparedStatement // ps = ct.prepareStatement("select * from dept where deptno=? and loc=?"); // //设置参数 // ps.setInt(1, 20); // ps.setString(2, "dallas"); // //执行查询 // rs = ps.executeQuery(); // // while(rs.next()){ // System.out.println(rs.getInt(1) + " " + rs.getString(2) + " " + rs.getString(3)); // } //插入 //创建PreparedStatement ps = ct.prepareStatement("insert into dept values(?,?,?)"); //设置参数 ps.setInt(1, 50); ps.setString(2, "deploy"); ps.setString(3, "beijing"); //执行插入 int res = ps.executeUpdate(); if(res == 1){ System.out.println("insert."); } else { System.out.println("failure."); } } catch (Exception e) { e.printStackTrace(); } finally{ //关闭资源 try{ if(rs != null){ rs.close(); } if(ct != null){ ct.close(); } if(ps != null){ ps.close(); } }catch (Exception e2) { e2.printStackTrace(); } } } } ~~~ ### JDBC-ODBC桥连操作sql server与JDBC驱动直连操作sql server的区别: 1、JDBC-ODBC桥连sql server无需引入外部驱动 2、JDBC直连需要引入微软提供的JDBC驱动 ~~~ /** * jdbc方式操纵数据库 * 1.引入java.sql.*; * 2.引入jar包 * 3.sqlserver2000需要引入三个jar包,分别是msbase.jar和mssqlserver.jar和msutil.jar * 4.sqlserver2005/2008/2012版本中可以引入sqljdbc.jar或sqljdbc4.jar两个微软提供的JDBC包,官方目前推出2.0/3.0/4.0版本 * 5.使用sqljdbc4.jar后可以不使用加载驱动Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");而直接连接数据库 * 6.使用sqljdbc.jar则需要加载驱动 * 7.特别说明,如果取值是按编号取,则需一一对应;如果按字段列名取值,则可以灵活取值 */ package com.db; import java.sql.*; public class db3 { public static void main(String[] args) { // 定义 Connection ct = null; PreparedStatement ps = null; ResultSet rs = null; try { // 初始化对象 // 1.加载驱动 Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); // 2.得到连接 ct = DriverManager.getConnection( "jdbc:sqlserver://127.0.0.1:1433; DatabaseName=db", "sa", "123456"); // //3.创建PraparedStatement // ps = ct.prepareStatement("select * from emp"); // //4.执行(如果是增删改使用executeUpdate(),如果是查询则使用executeQuery()) // rs = ps.executeQuery(); // // //循环取出员工的名字,薪水,部门编号 // while(rs.next()){ // String ename = rs.getString("ename"); // float sal = rs.getFloat(6); // int deptno = rs.getInt(8); // System.out.println(ename + " " + sal + " " + deptno); // } // //3.创建PraparedStatement // ps = // ct.prepareStatement("select ename,sal,dname from emp,dept where emp.deptno = dept.deptno "); // //4.执行(如果是增删改使用executeUpdate(),如果是查询则使用executeQuery()) // rs = ps.executeQuery(); // // //循环取出员工的名字,薪水,部门名称 // while(rs.next()){ // String ename = rs.getString("ename"); // float sal = rs.getFloat("sal"); // String deptName = rs.getString("dname"); // System.out.println(ename + " " + sal + " " + deptName); // } // 3.创建PraparedStatement ps = ct.prepareStatement("insert into dept values(?,?,?)"); // 4.执行(如果是增删改使用executeUpdate(),如果是查询则使用executeQuery()) // 赋值 ps.setInt(1, 60); ps.setString(2, "software"); ps.setString(3, "beijing"); int res = ps.executeUpdate(); if (res == 1) { System.out.println("insert."); } else { System.out.println("failure."); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (rs != null) { rs.close(); } if (ps != null) { ps.close(); } if (ct != null) { ct.close(); } } catch (SQLException e) { e.printStackTrace(); } } } } ~~~ ### java程序中来控制对数据库(表)的创建、删除、备份、恢复工作 ~~~ /** * 在java中如何使用ddl语句(create,drop,backup...) */ package com.db; import java.sql.*; public class db4 { public static void main(String[] args) { Connection ct = null; PreparedStatement ps = null; ResultSet rs = null; try { // 初始化对象 // 1.加载驱动 Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); // 2.得到连接 ct = DriverManager.getConnection( "jdbc:sqlserver://127.0.0.1:1433; DatabaseName=db", "sa", "123456"); // 3.创建PrepareStatement //创建数据库 //ps = ct.prepareStatement("create database test"); //创建表 //ps = ct.prepareStatement("create table test2(tNo int)"); //备份数据库 ps = ct.prepareStatement("backup database test to disk='C:/test.bak'"); // 执行ddl语句 boolean b = ps.execute(); if(!b){ System.out.println("ok"); }else{ System.out.println("failure"); } } catch (Exception e) { e.printStackTrace(); } finally { // 关闭连接 try { if (rs != null) { rs.close(); } if (ps != null) { ps.close(); } if (ct != null) { ct.close(); } } catch (Exception e2) { e2.printStackTrace(); } } } } ~~~ ### 实例:学生管理系统 ### JTable的使用 ~~~ /** * JTable的使用 */ package com.db; import javax.swing.*; import java.util.*; import java.sql.*; import java.awt.*; import java.awt.event.*; public class db5 extends JFrame{ //rowData用来存放行数据 //columnNames存放列名 Vector rowData; //columnNames存放列名 Vector columnNames; //定义组件 JTable jt = null; JScrollPane jsp = null; //构造方法 public db5(){ columnNames = new Vector(); //设置列名 columnNames.add("学号"); columnNames.add("名字"); columnNames.add("性别"); columnNames.add("年龄"); columnNames.add("籍贯"); columnNames.add("系别"); rowData = new Vector(); //rowData存放多行 Vector row = new Vector(); row.add("001"); row.add("张三"); row.add("男"); row.add("20"); row.add("湖南"); row.add("软件工程"); //加入到rowData rowData.add(row); //创建组件 jt = new JTable(rowData, columnNames); jsp = new JScrollPane(jt); //添加到JFrame add(jsp); //设置窗体 setTitle("JTable的使用"); setSize(400, 300); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } public static void main(String[] args) { db5 gui1 = new db5(); } } ~~~ ### JTable显示从数据库读取的学生信息 ~~~ /** * 从数据库读取学生信息 */ package com.db; import java.util.Vector; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import java.sql.*; public class db6 extends JFrame { // 定义数据库资源 Connection ct = null; PreparedStatement ps = null; ResultSet rs = null; // rowData用来存放行数据 // columnNames存放列名 Vector rowData; // columnNames存放列名 Vector columnNames; // 定义组件 JTable jt = null; JScrollPane jsp = null; // 构造方法 public db6() { columnNames = new Vector(); // 设置列名 columnNames.add("学号"); columnNames.add("名字"); columnNames.add("性别"); columnNames.add("年龄"); columnNames.add("籍贯"); columnNames.add("系别"); rowData = new Vector(); // rowData存放多行 // 从数据库取数据 try { // 加载驱动 Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); // 获取连接 ct = DriverManager.getConnection( "jdbc:sqlserver://127.0.0.1:1433; DatabaseName=StuManage", "sa", "123456"); // 创建PreparedStatement ps = ct.prepareStatement("select * from stu"); // 执行查询 rs = ps.executeQuery(); // 循环获取数据 while (rs.next()) { // rowData存放多行数据 // 定义一行数据 Vector row = new Vector(); row.add(rs.getInt("stuId")); row.add(rs.getString("stuName")); row.add(rs.getString("stuSex")); row.add(rs.getInt("stuAge")); row.add(rs.getString("stujg")); row.add(rs.getString("stuDept")); // 添加到rowData rowData.add(row); } } catch (Exception e) { e.printStackTrace(); } finally { // 关闭资源 try { if (rs != null) { rs.close(); } if (ps != null) { ps.close(); } if (ct != null) { ct.close(); } } catch (Exception e2) { e2.printStackTrace(); } } // 创建组件 jt = new JTable(rowData, columnNames); jsp = new JScrollPane(jt); // 添加到JFrame add(jsp); // 设置窗体 setTitle("JTable的使用"); setSize(400, 300); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } public static void main(String[] args) { db6 ui = new db6(); } } ~~~ ### Mini学生管理系统 ~~~ --创建数据库 create database StuManage; --使用数据库 use StuManage; --创建学生表 create table stu ( stuId int primary key identity(10000,1), --学号 stuName nvarchar(50) not null, --姓名 stuSex nchar(1) check(stuSex in('男','女')) default '男', --性别 stuAge int check(stuAge > 1), --年龄 stujg nvarchar(30), --籍贯 stuDept nvarchar(40) --专业 ); --插入数据 insert into stu values('张三','男',20,'湖南','软件工程'); insert into stu values('李四','男',25,'湖北','通信工程'); insert into stu values('王五','男',15,'河北','制药工程'); insert into stu values('赵丽','女',21,'湖南','英语'); --查询 select * from stu; ~~~ ![](https://box.kancloud.cn/2016-02-25_56ceb3e33f6cb.jpg) #### Model1模式 源码:[https://code.csdn.net/snippets/1367849](https://code.csdn.net/snippets/1367849) ![](https://box.kancloud.cn/2016-02-25_56ceb3e361db9.jpg) #### Model2模式 源码:[https://code.csdn.net/snippets/1367938](https://code.csdn.net/snippets/1367938) ![](https://box.kancloud.cn/2016-02-25_56ceb3e39faa5.jpg) #### Model2模式改进 源码:[https://code.csdn.net/snippets/1367979](https://code.csdn.net/snippets/1367979) ----------参考《韩顺平.循序渐进学.java.从入门到精通》 ----------参考《JDK_API_1_6_zh_CN》 Java学习笔记--导航[http://blog.csdn.net/q547550831/article/details/49819641](http://blog.csdn.net/q547550831/article/details/49819641)