tlsmile 2020-06-05
一、三大范式
1、第一范式:原子性 保证每一列不可再分
2、第二范式:在满足第一范式的前提下,每张表只能描述一件事情
3、第三范式:在满足第一第二范式的前提下,第三范式需要确保数据表中的每一列数据都和主键直接相关,不能间接相关。
规范数据库的设计:规范性和性能的问题
阿里规范:关联查询的表不得超过三张表
·考虑商业化得需求和目标(成本和用户体验)数据库得性能更加重要
·在规范性能得问题得时候,需要适当的考虑一下规范性
·故意给某些表增加一些冗余得字段(从多表查询变为单表查询)
·故意增加一些计算列(从大数据量降低为小数据量得查询)//或者用索引,但索引树比较占内存
二、JDBC
用Java操作数据库,程序通过数据库驱动和数据库打交道。
每个公司有每个公司得数据库驱动,mysql oracle...
sun公司为了简化开发人员得操作,提供了一个Java操作数据库得规范,俗称JDBC
这些规范的实现由具体得厂商去做
三、Java做JDBC的原理
其实就是在可视化工具中做的操作用Java代码实现。
正常第一步,打开可视化工具(加载驱动),输入用户名密码和url对数据库进行连接 连接成功相当于返回了一个数据库对象
第二部,编写完sql之后执行sql 就这么简单。
package space.urbeautiful.jdbc; import java.sql.*; public class jdbcTest { public static void main(String[] args) throws ClassNotFoundException, SQLException { //1、加载驱动 Class.forName("com.mysql.jdbc.Driver");//固定写法,加载驱动 //2、用户信息和url //useUnicode=true&characterEncoding=utf&useSSL=true"; //useUnicode=true--支持中文编码 characterEncoding=utf8--字符集为utf8 utf&useSSL=false--使用安全连接 String url = "jdbc:mysql://localhost:3306/jzspace?useUnicode=true&characterEncoding=utf8&useSSL=true"; String userName = "root"; String password = "space999"; //3、连接成功 返回一个数据库对象 这个Connection就代表数据库 Connection conn = DriverManager.getConnection(url, userName, password);//驱动管理来获得连接 //4、执行SQL的对象 Statement执行sql的对象 Statement stat = conn.createStatement(); //5、SQL的对象去执行sql 执行完毕可能存在结果,查看返回结果 String sql = "select * from users"; ResultSet resultSet = stat.executeQuery(sql);//返回的结果集,结果集中封装了所有我们查出来的结果,是一个链表形式 while(resultSet.next()){ System.out.println("id" + resultSet.getObject("id")); System.out.println("name" + resultSet.getObject("name")); System.out.println("psw" + resultSet.getObject("psw")); System.out.println("email" + resultSet.getObject("email")); System.out.println("birthday" + resultSet.getObject("birthday")); } //6、释放连接 resultSet.close(); stat.close(); conn.close(); } }
1、加载驱动 Class.forName("");
2、用户信息和url
3、连接数据库 DriverManager.getConnection();
4、创建一个执行sql的对象 Statement
5、sql语句用statement执行 stat.executeQuery()执行查询语句 stat.executeUpdate()执行update insert delete等操作
6、加载结果集数据
7、关闭连接 从下到上
JAVA万物皆对象,所以将这些操作都整合成为对象来进行操作。
四、详解JDBC-->JAVA中的对象
1、DriverManager
//DriverManager.registerDriver(new com.mysql.jdbc.Driver()); Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection(url,username,password);//Connection代表数据库 用数据库写的代码它都能写 他就是数据库的对象//数据库设置自动提交//事务提交 事务回滚conn.commit();conn.rollback();conn.setAutoCommit();//设置自动连接 //推荐使用Class.forName 加载驱动 //上面那个是注册驱动,在Driver()方法中的静态代码块中已经给注册了一个驱动,可能出现重读注册驱动 /* static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can‘t register driver!"); } } */
2、URL
String url = "jdbc:mysql://localhost:3306/jzspace?useUnicode=true&characterEncoding=utf8&useSSL=true"; /* jdbc:mysql://localhost:3306 直接看作是一个网址 jdbc:mysql看作是https这种协议 localhost 看作主机名 3306 看作端口号 公式:协议://主机地址:端口号/数据库名?参数1&参数2&参数3 oracle的写法: jdbc:oracle:thin:@localhost:1521:sid */
3、Statement执行SQL的对象 PrepareStatement执行SQL的对象
String sql = "select * from users";//编写sql statement.executeQuery();//查询操作返回结果集ResultSeet statement.execute();//执行任何sql statement.executeUpdate();//更新,插入,删除都使用这个,返回一个受影响的行数
4、ResultSet 结果集 只有查询操作才有结果集 封装了所有的查询结果
//在不知道列类型的情况下使用getObject() resultSet.getObject(); //如果知道列类型就使用指定的类型 resultSet.getString(); resultSet.getInt(); resultSet.getFloat(); resultSet.getDate(); //...
5、遍历结果集
resultSet.next();//移动到下一个数据
6、释放资源
resultSet.close(); stat.close(); conn.close();//十分耗资源,用完关掉!
五、详解Statement对象
Jdbc中的statement对象适用于向数据库发送sql语句,像完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查的语句即可。
Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,execcuteUpdate执行完后,将会返回一个整数(即增删改语句导致数据库几行数据发生了变化)
Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象
1、CRUD操作-insert 使用executeUpdate(String sql)方法完成数据添加操作:
Statement stat = conn.createStatement(); String sql = "insert into table(...) values(...)"; int num = stat.executeUpdate(sql); if(num>0){ System.out.println("插入成功"); }
2、CRUD操作-delete 使用executeUpdate(String sql)方法完成数据删除操作:
Statement stat = conn.createStatement(); String sql = "delete from student where StudentNo=1004"; int num = stat.executeUpdate(sql); if(num>0){ System.out.println("删除成功"); }
3、CRUD操作-update 使用executeUpdate(String sql)方法完成数据更新操作:
Statement stat = conn.createStatement(); String sql = "update table set column=‘‘ where id=‘‘"; int num = stat.executeUpdate(sql); if(num>0){ System.out.println("更新成功"); }
4、CRUD操作-select 使用executeQuery(String sql)方法完成数据查询操作:
Statement stat = conn.createStatement(); String sql = "select * from users"; ResultSet resultSet = stat.executeQuery(sql); while(resultSet.next()){ //根据获取列的数据类型,分别调用resultSet的相应方法映射到Java对象中}
六、代码实现 有很多方法我们需要经常写,那我们就需要封装一些工具类
因为Statement是执行sql语句的,所以需要进行操作,这种我们就不需要封装
要封装的有Connection连接和释放连接。
首先将用户信息写到配置文件中:
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/jzspace?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC username=root password=space999
下面是封装的代码:
package space.urbeautiful.utils; import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class JdbcUtils { private static String driver = null; private static String username= null; private static String url = null; private static String password = null; static{ try{ //将配置文件放入流中 InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties"); //读取配置文件的类 Properties properties = new Properties(); //加载流中的配置文件 properties.load(in); //从文件中读取出来内容 driver = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); //加载驱动 Class.forName(driver); } catch (Exception e) { e.printStackTrace(); } } //获取连接 public static Connection getConn() throws SQLException { return DriverManager.getConnection(url,username,password); } //释放资源 public static void release(Connection conn,Statement stat,ResultSet rs){ if(rs!=null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(stat!=null) { try { stat.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
下面测试一个insert的JDBC:
package space.urbeautiful.utils; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class TestInsert { public static void main(String[] args) { Connection conn = null; Statement stat = null; ResultSet rs = null; try { conn = JdbcUtils.getConn(); stat = conn.createStatement(); String sql = "insert into student(StudentNO,StudentName,sex,birthday,Address,email) " + "values(‘1004‘,‘迈巴赫‘,‘男‘,‘1996-09-09‘,‘浙江省‘,‘‘)"; int i = stat.executeUpdate(sql); if(i>0){ System.out.println("插入成功 --> insert " + i + "条数据"); } } catch (SQLException e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn,stat,rs); } } } /* 下面说一个我在学习JDBC的时候碰到的错误和解决方法 因为我的MySQL版本是8.0,所以我和秦老师下的版本是不一样的 在加载驱动时写的是:class.forName("com.mysql.jdbc.Driver") 报的错误是:Loading class `com.mysql.jdbc.Driver‘. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver‘. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary. 我也没仔细读,大致意思就是"com.mysql.jdbc.Driver"这句话写错了 应该写成`com.mysql.cj.jdbc.Driver‘. 改了之后还是出现了一个错误:java.sql.SQLException: The server time zone value ‘?й???????‘ is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the ‘serverTimezone‘ configuration property) to use a more specifc time zone value if you want to utilize time zone support. 那么百度:大概就是一个时区的问题,在url后面添加一个serverTimezone=UTC就解决了 */ /* 如果你用编译器连接数据库,定义了serverTimezone=UTC,那么在你编译器上执行的SQL语句,会先以UTC时区进行存储,发送到MySQL,然后MySQL以本地时区进行转换,就会导致,执行时间比从编译器上的执行时间早8个小时,导致,同一段SQL语句,在mysql直接执行,与编译器执行,结果不同,因为时间相差8个小时 原文链接:https://blog.csdn.net/baidu_38837718/article/details/104981617 */