1、,Java入门,4 Java数据库技术,4.1 MySQL和JDBC 4.2 使用JDBC 4.3 实例,4.1 MySQL和JDBC概述,MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司。MySQL 最流行的关系型数据库管理系统,在 WEB 应用方面MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一,对于一般的个人使用者和中小型企业来说,MySQL提供的功能绰绰有余。,创建数据库test: create database test 创建表her
2、o: CREATE TABLE hero (id int(11) AUTO_INCREMENT,name varchar(30) ,hp float ,damage int(11) ,PRIMARY KEY (id) ) DEFAULT CHARSET=utf8; 插入一条记录盖伦到表中:insert into hero values (null, 盖伦, 616, 100) 查询所有数据:select * from hero 统计表中有多少条数据:select count(*) from hero 显示前5条数据:select * from hero limit 0,5 修改:update
3、hero set hp = 818 where id = 1 删除:delete from hero where id = 1,操作语句,4.1 MySQL和JDBC,JDBC(Java Database Connection,Java数据库连接)是一种用于执行SQL语句的JavaAPI(应用程序设计接口),它由一些Java语言写的类和界面组成。JDBC提供了一种标准的应用程序设计接口,使得开发人员使用Java语言开发完整的数据库应用程序变得极为简单。通过JDBC,开发人员几乎可以将SQL语句传递给任何一种数据库,而无需为各种数据库编写单独的访问程序。JDBC可以自动将SQL语句传递给相应的数
4、据库管理系统。,访问MySQL数据库需要用到第三方的类,这些第三方的类,都被压缩在一个叫做Jar的文件里。 为了代码能够使用第三方的类,需要为项目导入mysql的专用Jar包。 mysql-connector-java-5.0.8-bin.jar 通常都会把项目用到的jar包统一放在项目的lib目录下导包步骤: 右键project-property-java build path-libaries-add external jars,package jdbc;public class TestJDBC public static void main(String args) /初始化驱动try
5、 /驱动类com.mysql.jdbc.Driver/就在 mysql-connector-java-5.0.8-bin.jar中/如果忘记了第一个步骤的导包,就会抛出ClassNotFoundExceptionClass.forName(“com.mysql.jdbc.Driver“);System.out.println(“数据库驱动加载成功 !“); catch (ClassNotFoundException e) / TODO Auto-generated catch blocke.printStackTrace(); ,初始化驱动 通过Class.forName(“com.mysql
6、.jdbc.Driver“);初始化驱动类com.mysql.jdbc.Driver 就在 mysql-connector-java-5.0.8-bin.jar中,JDBC扩展了Java的功能,例如在Applet中应用JDBC,可以实现与远程数据库的连接,实现不同平台数据库之间的对话。简单地说,JDBC完成下面三个操作:(1) 与一个数据库建立连接。Connection con = DriverManager.getConnection(“jdbc:odbc:CallCenter“,“sa“,“);(2) 向数据库发送SQL语句。stmt = con.createStatement(); rs
7、 = stmt.executeQuery(“SELECT CID,CPin from tCustomer WHERE CID=z1“);,(3) 处理数据库返回的结果。 while(rs.next() String theInt = rs.getString(“CID“);String str = rs.getString(“CPin“);. ,4.2 使 用JDBC,JDBC的接口分为两个层次:一个是面向程序开发人员的JDBC API;另外一个是底层的JDBC Driver API。JDBC API 被描述成为一组抽象的Java接口,应用程序可以对某个数据库打开连接,执行SQL语句并且处理结
8、果。最重要的接口如下:java.sql.DriverManager:处理驱动的调入并且对产生新的数据库连接提供支持。java.sql.Connection:代表对特定数据库的连接。java.sql.Statement:代表一个特定的容器,以对一个特定的数据库执行SQL语句。java.sql.ResultSet:控制对一个特定语句的行数据的存取。,其中java.sql.Statement又有两个子类型:(1) java.sql.PreparedStatement:用于执行预编译的SQL语句。(2) java.sql.CallableStatement:用于执行对一个数据库内嵌过程的调用。JDBC
9、 Driver API是指java.sql.Driver接口,封装了不同数据库的驱动程序(像Access、Foxpro、SQL Server等)。由于它是数据库底层处理,所以必须提供对java.sql.Connection、java.sql. Statement、java.sql.PreparedStatement和java.sql.ResultSet的实现。,package jdbc;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException;public class Test
10、JDBC public static void main(String args) try Class.forName(“com.mysql.jdbc.Driver“);/ 建立与数据库的Connection连接/ 这里需要提供:/ 数据库所处于的ip:127.0.0.1 (本机)/ 数据库的端口号: 3306 (mysql专用端口号)/ 数据库名称 how2java/ 编码方式 UTF-8/ 账号 root/ 密码 admin,连接数据库,/接上面的代码 Connection c = DriverManager.getConnection(“jdbc:mysql:/127.0.0.1:330
11、6/test?characterEncoding=UTF-8“,“root“, “admin“);System.out.println(“连接成功,获取连接对象: “ + c); catch (ClassNotFoundException e) / TODO Auto-generated catch blocke.printStackTrace(); catch (SQLException e) / TODO Auto-generated catch blocke.printStackTrace(); ,package jdbc;import java.sql.Connection; impo
12、rt java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement;public class TestJDBC public static void main(String args) try Class.forName(“com.mysql.jdbc.Driver“);,Statement是用于执行SQL语句的,比如增加,删除,Connection c = DriverManager.getConnection(“jdbc:mysql:/127.0.0.1:3306/test?character
13、Encoding=UTF-8“,“root“, “admin“);/ 注意:使用的是 java.sql.Statement/ 不要不小心使用到: com.mysql.jdbc.Statement;Statement s = c.createStatement();System.out.println(“获取 Statement对象: “ + s); catch (ClassNotFoundException e) / TODO Auto-generated catch blocke.printStackTrace(); catch (SQLException e) / TODO Auto-ge
14、nerated catch blocke.printStackTrace(); ,package jdbc;import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement;public class TestJDBC public static void main(String args) try Class.forName(“com.mysql.jdbc.Driver“);Connection c = DriverManager
15、.getConnection(“jdbc:mysql:/127.0.0.1:3306/test?characterEncoding=UTF-8“,“root“, “admin“);,s.execute执行sql语句 执行成功后,用mysql-front进行查看,明确插入成功,Statement s = c.createStatement();/ 准备sql语句/ 注意: 字符串要用单引号String sql = “insert into hero values(null,“+“提莫“+“,“+313.0f+“,“+50+“)“; s.execute(sql);System.out.printl
16、n(“执行插入语句成功“); catch (ClassNotFoundException e) / TODO Auto-generated catch blocke.printStackTrace(); catch (SQLException e) / TODO Auto-generated catch blocke.printStackTrace(); ,执行SQL语句之前要确保数据库test中有表hero的存在,如果没有,需要事先创建表,在回收垃圾语句后面加上下面语句finally / 数据库的连接时有限资源,相关操作结束后,养成关闭数据库的好习惯/ 先关闭Statementif (s !
17、= null)try s.close(); catch (SQLException e) / TODO Auto-generated catch blocke.printStackTrace();/ 后关闭Connectionif (c != null)try c.close(); catch (SQLException e) / TODO Auto-generated catch blocke.printStackTrace(); ,数据库的连接是有限资源,相关操作结束后,养成关闭数据库的好习惯 先关闭Statement 后关闭Connection,package jdbc;import j
18、ava.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement;public class TestJDBC public static void main(String args) try Class.forName(“com.mysql.jdbc.Driver“); catch (ClassNotFoundException e) e.printStackTrace();,使用try-with-resource的方式自动关闭连接,try (Co
19、nnection c = DriverManager.getConnection(“jdbc:mysql:/127.0.0.1:3306/test?characterEncoding=UTF-8“,“root“, “admin“);Statement s = c.createStatement(); )String sql = “insert into hero values(null,“ + “提莫“ + “,“ + 313.0f + “,“ + 50 + “)“;s.execute(sql); catch (SQLException e) / TODO Auto-generated cat
20、ch blocke.printStackTrace(); ,String sql = “insert into hero values(null,“ + “提莫“ + “,“ + 313.0f + “,“ + 50 + “)“;String sql = “delete from hero where id = 5“;String sql = “update hero set name = name 5 where id = 3“;,增、删、改语句,package jdbc;import java.sql.Connection; import java.sql.DriverManager; im
21、port java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement;public class TestJDBC public static void main(String args) try Class.forName(“com.mysql.jdbc.Driver“); catch (ClassNotFoundException e) e.printStackTrace();try (Connection c = DriverManager.getConnection(“jdbc:mysql:/12
22、7.0.0.1:3306/test?characterEncoding=UTF-8“,“root“, “admin“); Statement s = c.createStatement();) ,executeQuery 执行SQL查询语句,String sql = “select * from hero“;/ 执行查询语句,并把结果集返回给ResultSetResultSet rs = s.executeQuery(sql);while (rs.next() int id = rs.getInt(“id“);/ 可以使用字段名String name = rs.getString(2);/ 也
23、可以使用字段的顺序float hp = rs.getFloat(“hp“);int damage = rs.getInt(4);System.out.printf(“%dt%st%ft%d%n“, id, name, hp, damage);/ 不一定要在这里关闭ReultSet,因为Statement关闭的时候,会自动关闭ResultSet/ rs.close(); catch (SQLException e) / TODO Auto-generated catch blocke.printStackTrace(); ,在取第二列的数据的时候,用的是rs.get(2) ,而不是get(1).
24、 这个是整个Java自带的api里唯二的地方,package jdbc;import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException;public class TestJDBC public static void main(String args) try Class.forName(“com.mysql.jdbc.Driver“); catch (ClassNotFoundException e) e.pri
25、ntStackTrace();,PreparedStatement 也是用来执行sql语句的与创建Statement不同的是,需要根据sql语句创建PreparedStatement除此之外,还能能够通过设置参数,指定相应的值,而不是Statement那样使用字符串拼接,String sql = “insert into hero values(null,?,?,?)“;try (Connection c = DriverManager.getConnection(“jdbc:mysql:/127.0.0.1:3306/test?characterEncoding=UTF-8“,“root“,
26、 “admin“);/ 根据sql语句创建PreparedStatementPreparedStatement ps = c.prepareStatement(sql);) / 设置参数ps.setString(1, “提莫“);ps.setFloat(2, 313.0f);ps.setInt(3, 50);/ 执行ps.execute(); catch (SQLException e) / TODO Auto-generated catch blocke.printStackTrace();,使用参数设置,可读性好,不易犯错 有预编译机制,性能比Statement更快 防止SQL注入式攻击,
27、package jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement;public class TestJDBC public static void main(String args) try Class.forName(“com.mysql.jdbc.Driver“); catch (ClassNotFoundException e) e.printStackTrace();try (Connection
28、 c = DriverManager.getConnection(“jdbc:mysql:/127.0.0.1:3306/test?characterEncoding=UTF-8“,“root“, “admin“);Statement s = c.createStatement();) / 有事务的前提下/ 在事务中的多个操作,要么都成功,要么都失败,使用事务 在事务中的多个操作,要么都成功,要么都失败 通过 c.setAutoCommit(false);关闭自动提交 使用 mit();进行手动提交,c.setAutoCommit(false);/ 加血的SQLString sql1 = “u
29、pdate hero set hp = hp +1 where id = 22“;s.execute(sql1);/ 减血的SQL/ 不小心写错写成了 updata(而非update)String sql2 = “updata hero set hp = hp -1 where id = 22“;s.execute(sql2);/ 手动提交mit(); catch (SQLException e) / TODO Auto-generated catch blocke.printStackTrace(); ,package charactor;public class Hero /增加id属性p
30、ublic int id;public String name;public float hp;public int damage;,ORM=Object Relationship Database Mapping 对象和关系数据库的映射 简单说,一个对象,对应数据库里的一条记录例:根据id返回一个Hero对象 先构建一个Hero类,package jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; im
31、port java.sql.Statement;import charactor.Hero;public class TestJDBC public static Hero get(int id) Hero hero = null;try Class.forName(“com.mysql.jdbc.Driver“); catch (ClassNotFoundException e) e.printStackTrace(); try (Connection c = DriverManager.getConnection(“jdbc:mysql:/127.0.0.1:3306/test?chara
32、cterEncoding=UTF-8“,“root“, “admin“);Statement s = c.createStatement();) String sql = “select * from hero where id = “ + id;,ResultSet rs = s.executeQuery(sql);/ 因为id是唯一的,ResultSet最多只能有一条记录/ 所以使用if代替whileif (rs.next() hero = new Hero();String name = rs.getString(2);float hp = rs.getFloat(“hp“);int d
33、amage = rs.getInt(4);hero.name = name;hero.hp = hp;hero.damage = damage;hero.id = id; catch (SQLException e) / TODO Auto-generated catch blocke.printStackTrace();return hero; public static void main(String args) Hero h = get(22);System.out.println(h.name); ,package jdbc; import java.util.List;public
34、 interface DAO/增加public void add(T t);/修改public void update(T t);/删除public void delete(int id);/获取public T get(int id);/查询public List list();/分页查询public List list(int start, int count); ,DAO=Database Access Object 数据库访问对象 实际上就是运用了练习-ORM中的思路,把数据库相关的操作都封装在这个类里面,其他地方看不到JDBC的代码,package jdbc;import java.
35、sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.List;import charactor.Hero;public class HeroDAO ,把驱动的初始化放在了构造方法HeroDAO里:因为驱动初始化值需要执行一次,所以
36、放在这里更合适,其他方法里也不需要写了,代码更简洁。 提供了一个getConnection方法返回连接,所有的数据库操作都需要事先拿到一个数据库连接Connection,以前的做法每个方法里都会写一个,如果要改动密码,那么每个地方都需要修改。 通过这种方式,只需要修改这一个地方就可以了。 代码变得更容易维护,而且也更加简洁。,public HeroDAO() try Class.forName(“com.mysql.jdbc.Driver“); catch (ClassNotFoundException e) e.printStackTrace();public Connection getC
37、onnection() throws SQLException return DriverManager.getConnection(“jdbc:mysql:/127.0.0.1:3306/test?characterEncoding=UTF-8“, “root“,“admin“);,public int getTotal() int total = 0;try (Connection c = getConnection(); Statement s = c.createStatement();) String sql = “select count(*) from hero“;ResultS
38、et rs = s.executeQuery(sql);while (rs.next() total = rs.getInt(1);System.out.println(“total:“ + total); catch (SQLException e) e.printStackTrace();return total;,public void add(Hero hero) String sql = “insert into hero values(null,?,?,?)“;try (Connection c = getConnection(); PreparedStatement ps = c
39、.prepareStatement(sql);) ps.setString(1, hero.name);ps.setFloat(2, hero.hp);ps.setInt(3, hero.damage);ps.execute();ResultSet rs = ps.getGeneratedKeys();if (rs.next() int id = rs.getInt(1);hero.id = id; catch (SQLException e) e.printStackTrace(); public void update(Hero hero) String sql = “update hero set name= ?, hp = ? , damage = ? where id = ?“;try (Connection c = getConnection(); PreparedStatement ps = c.prepareStatement(sql);) ps.setString(1, hero.name);ps.setFloat(2, hero.hp);ps.setInt(3, hero.damage);ps.setInt(4, hero.id);ps.execute(); catch (SQLException e) e.printStackTrace(); ,