回想“流与文件”章节,如何将一组对象存储到文件中?主要步骤是什么。
1.首先要将对象序列化,需要对象实现序列化接口,然后通过java的ObjectOutputStream的writeObject()方法将对象序列化的数据写到指定的文件中,再使用java 的 ObjectInputStream的readObject()方法来进行读取序列化后的文件
public class Person implements Serializable {
}
2. 主要步骤就是,使用Java集合架构储存数据,再使用流将数据存储到文件中
关系数据库中使用表存储数据。查询资料回答:表的设计应该遵循什么基本规范?如果要将Student对象(学号、姓名、年龄、分数、学院)存入数据库,要怎么设计表?设计几个表?
1.命名规范
数据库表名、字段名、索引名等都需要命名规范,可读性高(一般要求用英文),让别人一看命名,就知道这个字段表示什么意思。
account_no,account_number
复制代码
- 表名、字段名必须使用小写字母或者数字,禁止使用数字开头,禁止使用拼音,并且一般不使用英文缩写。
- 主键索引名为
pk_字段名
;唯一索引名为uk_字段名
;普通索引名则为idx_字段名
。
2.选择合适的字段类型
设计表时,我们需要选择合适的字段类型,比如:
- 尽可能选择存储空间小的字段类型,就好像数字类型的,从
tinyint、smallint、int、bigint
从左往右开始选择 - 小数类型如金额,则选择
decimal
,禁止使用float
和double
。 - 如果存储的字符串长度几乎相等,使用
char
varchar
是可变长字符串,不预先分配存储空间,长度不要超过5000
。- 如果存储的值太大,建议字段类型修改为
text
,同时抽出单独一张表,用主键与之对应。 - 同一表中,所有
varchar
字段的长度加起来,不能大于65535
. 如果有这样的需求,请使用TEXT/LONGTEXT
类型。
3. 主键设计要合理
主键设计的话,最好不要与业务逻辑有所关联。有些业务上的字段,比如身份证,虽然是唯一的,一些开发者喜欢用它来做主键,但是不是很建议哈。主键最好是毫无意义的一串独立不重复的数字,比如UUID
,又或者Auto_increment
自增的主键,或者是雪花算法生成的主键等等;
4. 选择合适的字段长度
其实在mysql中,
varchar
和char
类型表示字符长度,而其他类型表示的长度都表示字节长度。比如char(10)
表示字符长度是10,而bigint(4)
表示显示长度是4
个字节,但是因为bigint实际长度是8
个字节,所以bigint(4)的实际长度就是8个字节。
我们在设计表的时候,需要充分考虑一个字段的长度
5,优先考虑逻辑删除,而不是物理删除
- 物理删除:把数据从硬盘中删除,可释放存储空间
- 逻辑删除:给数据添加一个字段,比如
is_deleted
,以标记该数据已经逻辑删除。- 为什么不推荐使用物理删除,因为恢复数据很困难
- 物理删除会使自增主键不再连续
- 核心业务表 的数据不建议做物理删除,只适合做状态变更。
6. 每个表都需要添加这几个通用字段如主键、create_time、modifed_time等
表必备一般来说,或具备这几个字段:
- id: 主键,一个表必须得有主键,必须
- create_time: 创建时间,必须
- modifed_time: 修改时间,必须,更新记录时,需要更新它
- version : 数据记录的版本号,用于乐观锁,非必须
- remark :数据记录备注,非必须
- modified_by :修改人,非必须
- creator :创建人,非必须
7. 尽可能使用not null定义字段
如果没有特殊的理由, 一般都建议将字段定义为NOT NULL
。
为什么呢?
- 首先,
NOT NULL
可以防止出现空指针问题。 - 其次,
NULL
值存储也需要额外的空间的,它也会导致比较运算更为复杂,使优化器难以优化SQL。 NULL
值有可能会导致索引失效- 如果将字段默认设置成一个空字符串或常量值并没有什么不同,且都不会影响到应用逻辑, 那就可以将这个字段设置为
NOT NULL
。
8. 设计表时,评估哪些字段需要加索引
首先,评估你的表数据量。如果你的表数据量只有一百几十行,就没有必要加索引。否则设计表的时候,如果有查询条件的字段,一般就需要建立索引。但是索引也不能滥用:
- 索引也不要建得太多,一般单表索引个数不要超过
5
个。因为创建过多的索引,会降低写得速度。 - 区分度不高的字段,不能加索引,如性别等
- 索引创建完后,还是要注意避免索引失效的情况,如使用mysql的内置函数,会导致索引失效的
- 索引过多的话,可以通过联合索引的话方式来优化。然后的话,索引还有一些规则,如覆盖索引,最左匹配原则等等。
9. 不需要严格遵守 3NF,通过业务字段冗余来减少表关联
数据库三范式(3NF
)
- 第一范式:对属性的原子性,要求属性具有原子性,不可再分解;
- 第二范式:对记录的唯一性,要求记录有唯一标识,即实体的唯一性,即不存在部分依赖;
- 第三方式:对字段的冗余性,要求任何字段不能由其他字段派生出来,它要求字段没有冗余,即不存在传递依赖;
10. 避免使用MySQL保留字
如果库名、表名、字段名等属性含有保留字时,SQL
语句必须用反引号来引用属性名称,这将使得SQL语句书写、SHELL脚本中变量的转义等变得非常复杂。
因此,我们一般避免使用MySQL
保留字,如select、interval、desc
等等
如果要设计将Student对象(学号、姓名、年龄、分数、学院)存入数据库,需要设计两个表
第一个表为 学生信息表:包括学号,姓名,年龄,学院
第二个表为 学生成绩表:包括学号,姓名,分数
JDBC编程的一般步骤是哪些?
第一步:注册驱动(告诉Java程序,即将要连接那个品牌的数据库)
第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完后一定要关闭)
第三步:获取数据库操作对象(专门执行sql语句的对象)
第四步:执行SQL语句(DQL DML ...)
第五步:处理查询结果集(只有第四步执行select语句时,才会执行第五步)
第六步:释放资源(使用完资源后一定要关闭资源。Java和数据库属于进程间通信,开启后一定要关闭)
package com.xzh.jdbc;
import javax.xml.transform.Result;
import java.sql.*;
public class Test {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet res = null;
try {
// 第一步:注册驱动(告诉Java程序,即将要连接那个品牌的数据库)
Class.forName("com.mysql.jdbc.Driver");
// 第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完后一定要关闭)
String url = "jdbc:mysql://localhost:3306/xzh";
String user = "root";
String password = "333";
conn = DriverManager.getConnection(url, user, password);
// 第三步:获取数据库操作对象(专门执行sql语句的对象)
stmt = conn.createStatement();
// 第四步:执行SQL语句(DQL DML ...)
String sql = "select empno as a,ename from emp";
res = stmt.executeQuery(sql);// 专门执行DQL语句
// 专门执行DML语句的(insert delete update)
// 返回值是“影响数据库中的记录条数”
//int c =stmt.executeUpdate(sql);
// 第五步:处理查询结果集(只有第四步执行select语句时,才会执行第五步)
while (res.next()) {
String empno = res.getString("a");
String ename = res.getString("ename");
System.out.println(empno + "," + ename);
}
} catch (SQLException e) {
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
}finally {
// 第六步:释放资源(使用完资源后一定要关闭资源。Java和数据库属于进程间通信,开启后一定要关闭)
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
Statement与PreparedStatement有何区别?
1.PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程
2.使用 Statement 对象。在对数据库只执行一次性存取的时侯,用 Statement 对象进行处理。PreparedStatement 对象的开销比Statement大,对于一次性操作并不会带来额外的好处。
3.statement每次执行sql语句,相关数据库都要执行sql语句的编译,preparedstatement是预编译得, preparedstatement支持批处理
怎么将数据库中表的数据组装成一个对象?
可以先创建一个对象如Student,生成setter/getter等方法获取相应属性值;创建一个列表,循环把新生成对象赋值并加入列表