一、三大范式
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','浙江省','2770974690@qq.com')"; 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 */