一、mysql数据库
- 表结构的设计原则:
- 开发中处理一对多的问题:在多表(从表)中添加一个外键,名称一般为主表的名称_id,字段类型一般和主表保持一致,为了保证数据的有效性和完整性,在多表的外键上添加一个外键约束即可(但开发中基本不会添加,因为有约束后,操作单表很不方便,但是要有外键字段,且外键的联系要清楚)
- 开发中处理多对多的问题:引入一张中间表,存放两张表的主键,一般会将这两个字段设置为联合主键,这样就可以将多对多的关系拆分成两个一对多的了,为了保证数据的完整性和一致性,需要在中间表上添加两个外键约束即可。(实际中一般不会添加)
二、JDBC
- JDBC六步:
// 1.加载驱动 Class.forName("com.mysql.jdbc.Driver"); // 2.获取连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/qf", "root", "root"); // 3.编写sql语句,获得操作对象 String sql = "select * from student"; PreparedStatement st = conn.prepareStatement(sql); // 4.执行sql,返回结果 ResultSet rs = st.executeQuery(); // 5.处理结果 while (rs.next()) { System.out.println(rs.getString(1)); } // 6.关闭资源 rs.close(); st.close(); conn.close();
- 封装JDBC工具类,编写配置文件db.properties.注意配置文件一定要放在src目录下。(将操作方法同时封装进工具类中,方便后面的操作)
-
-
项目中新建普通文件夹:lib
-
拷贝所需jar包至该目录下
-
右键jar包 -> build path -> add to build path
-
/** * JDBC 工具类的封装 * * @author Administrator * */ public class DBUtil { private static Connection conn; private PreparedStatement prest; private ResultSet rs; //只要使用工具类必须要加载驱动和打开连接,所以可以放在静态代码块中 static { try { // 1.加载驱动 Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { throw new RuntimeException("驱动加载失败,请检查驱动"); } // 打开连接 openConnection(); } public DBUtil() { } /** * 2.打开一个连接 */ public static void openConnection() { try { // 读取配置文件 获得 数据库连接信息 Properties prop = new Properties(); prop.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties")); // 拿到对应的数据 String url = prop.getProperty("url"); String user = prop.getProperty("user"); String password = prop.getProperty("password"); // 拿到连接 conn = DriverManager.getConnection(url, user, password); } catch (Exception e) { throw new RuntimeException("连接获取失败"); } } /** * 3.拿到一个sql操作对象 * * @param sql要执行的sql * (会对sql进行预编译,防止sql注入) * @return 返回一个preparedStatement对象,其中包含了已经编译好的sql语句 */ public PreparedStatement getPrepareStatement(String sql) { try { prest = conn.prepareStatement(sql); } catch (SQLException e) { throw new RuntimeException("PrepareStatement对象获取失败"); } return prest; } /** * 4.封装查询的方法 * * @param sql * 查询的sql语句 * @param obj * 语句中问号的设置的值的数组 * @return rs 返回查询结果 */ public ResultSet executeQuery(String sql, Object obj[]) { // 先对sql预编译 拿到PrepareStatement对象 prest = getPrepareStatement(sql); try { // 循环给语句中的?赋值 if (obj != null) { for (int i = 0; i < obj.length; i++) { prest.setObject(i + 1, obj[i]); } } // 执行查询操作 rs = prest.executeQuery(); } catch (SQLException e) { e.printStackTrace(); } return rs; } /** * 5.封装更新的方法 * * @param sql * 需要执行的sql语句 * @param obj * 语句中?需要设置的值的数组 * @return 返回一个影响数据库的行数 */ public int executeUpdate(String sql, Object obj[]) { // 打印一下传入的sql 防止sql语句有误 // System.out.println(sql); // 拿到一个PrepareStatement对象,里面包含了预编译的sql语句 prest = getPrepareStatement(sql); // 更新结果的标志 int rs = 0; try { if (obj != null) { for (int i = 0; i < obj.length; i++) { prest.setObject(i + 1, obj[i]); } } // 执行更新操作 rs = prest.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); rs=-1; } return rs; } /** * 6.关闭资源 先打开的后关闭,后打开的先关闭 */ public void close() { try { // 先判空 if (rs != null) { rs.close(); } if (prest != null) { prest.close(); } if (conn != null) { conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } }