ORM思想

ORM思想

通俗易懂的ORM讲解

什么是ORM?

ORM(Object-Relational Mapping,对象关系映射)是一种编程技术,用于在面向对象编程语言中,将数据库中的表和数据映射到程序中的对象和属性。

简单来说,ORM让你可以用操作对象的方式来操作数据库,而不需要直接写SQL语句。

为什么要用ORM?

  • 简化代码:不用写复杂的SQL语句,直接用对象操作数据库
  • 提高开发效率:ORM框架自动处理数据库操作,开发者可以更专注于业务逻辑。
  • 减少错误:ORM框架会自动生成SQL语句,减少手写SQL带来的错误。
  • 跨数据库支持:ORM框架通常支持多种数据库,切换数据库时只需修改配置,代码基本不用改。

例子说明

假设你有一个Employee表,结构如下:

emp_id emp_name emp_salary emp_age
1 张三 5000.00 25
2 李四 6000.00 30

使用ORM,你可以这样写代码来查询数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 1. 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///xy", "root", "230320");
// 3. 创建Statement对象
Statement statement = connection.createStatement();
// 4. 执行SQL查询
ResultSet resultSet = statement.executeQuery("SELECT * FROM t_emp WHERE emp_id = 1");
// 5. 处理结果
Employee employee = null;
while (resultSet.next()) {
int empId = resultSet.getInt("emp_id");
String empName = resultSet.getString("emp_name");
Double empSalary = resultSet.getDouble("emp_salary");
int empAge = resultSet.getInt("emp_age");
employee = new Employee(empId, empName, empSalary, empAge);
}
// 6. 释放资源
resultSet.close();
statement.close();
connection.close();

ORM的核心思想

ORM的核心思想是将数据库中的表映射为程序中的类,表中的每一行数据映射为类的一个对象,表中的每一列映射为对象的一个属性。这样,你可以通过操作对象来操作数据库,而不需要直接写SQL语句。

ORM的优点

  • 面向对象:ORM让你可以用面向对象的方式操作数据库,符合现代编程思想。
  • 减少重复代码:ORM框架自动生成CRUD(增删改查)操作,减少重复代码。
  • 提高可维护性:代码更加简洁,易于维护和扩展。

ORM的缺点

  • 性能问题:ORM框架生成的SQL语句可能不够优化,影响性能。
  • 学习曲线:ORM框架通常有一定的学习曲线,初学者可能需要时间掌握。
  • 灵活性不足:对于复杂的查询,ORM可能不如手写SQL灵活。

总结

ORM是一种非常有用的技术,特别适合在大型项目中使用。它可以大大简化数据库操作,提高开发效率。虽然ORM有一些缺点,但在大多数情况下,它的优点远远超过了缺点。作为初学者,理解ORM的思想和使用方法是非常重要的,它将帮助你更好地进行数据库编程。

疑惑点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.xy.advanced.pojo;
public class Employee {
private Integer empId;//emp_id = empId 数据库中列名用下划线分隔,属性名用驼峰!
private String empName;//emp_name = empName
private Double empSalary;//emp_salary = empSalary
private Integer empAge;//emp_age = empAge
public Employee() {
}
public Employee(Integer empId, String empName, Double empSalary, Integer empAge) {
this.empId = empId;
this.empName = empName;
this.empSalary = empSalary;
this.empAge = empAge;
}
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Double getEmpSalary() {
return empSalary;
}
public void setEmpSalary(Double empSalary) {
this.empSalary = empSalary;
}
public Integer getEmpAge() {
return empAge;
}
public void setEmpAge(Integer empAge) {
this.empAge = empAge;
}
@Override
public String toString() {
return "Employee{" +
"empId=" + empId +
", empName='" + empName + '\'' +
", empSalary=" + empSalary +
", empAge=" + empAge +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Test
public void testORMList() throws Exception {
Connection connection = DriverManager.getConnection("jdbc:mysql:///xy", "root","230320");
PreparedStatement preparedStatement = connection.prepareStatement("select emp_id,emp_name,emp_salary,emp_age from t_emp");
ResultSet resultSet = preparedStatement.executeQuery();
Employee employee = null;
List<Employee> employeeList = new ArrayList<>();
while (resultSet.next()) {
employee =new Employee();
int empId = resultSet.getInt("emp_id");
String empName = resultSet.getString("emp_name");
Double empSalary = Double.valueOf(resultSet.getString("emp_salary"));
int empAge = resultSet.getInt("emp_age");

employee.setEmpId(empId);
employee.setEmpName(empName);
employee.setEmpSalary(empSalary);
employee.setEmpAge(empAge);
employeeList.add(employee);
}
for (Employee emp : employeeList) {
System.out.println(emp);
}
resultSet.close();
preparedStatement.close();
connection.close();
}

List

List employeeList = new ArrayList<>();
这里使用List的原因是:

为什么要用List

  • 存储多个对象List是一个容器,可以存储多个Employee对象。比如你查出来10个员工的数据,就可以把这10个对象都存到List里。
  • 方便操作:有了List,你可以很方便地对这些员工数据进行遍历、筛选、排序等操作。

为什么要用List<Employee>

  • 场景需求:假设你有一个Employee表,里面有多个员工的数据。你想把这些数据都查出来,然后在程序里处理。
  • 问题:如果不用List,你只能一个一个地处理员工数据,没法把它们集中在一起。
  • 解决方案:用List<Employee>,可以把查出来的所有员工数据都存到一个列表里,方便后续统一处理(比如打印、计算、筛选等)。

Employee employee = null

为什么要先Employee employee = null,而不是直接employee = new Employee()

  • 原因:这是一个编程习惯和优化问题。
    • 避免重复创建对象:如果直接在循环里employee = new Employee(),每次循环都会创建一个新的Employee对象。虽然这样也能工作,但会浪费内存。
    • 复用对象:先在循环外声明employee,然后在循环内复用这个对象,可以减少内存开销。
    • 代码清晰employee = null表示这个变量一开始是空的,等到需要的时候再赋值,逻辑更清晰。

因此:

  • List的作用:存储多个Employee对象,方便统一管理。
  • Employee employee = null的作用:避免重复创建对象,优化内存使用。

不用list的方法

方式 1:在循环中直接打印每个对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@Test
public void testORMWithoutList() throws Exception {
// 1. 获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///xy", "root", "230320");

// 2. 创建PreparedStatement对象,预编译SQL
PreparedStatement preparedStatement = connection.prepareStatement("select emp_id, emp_name, emp_salary, emp_age from t_emp");

// 3. 执行查询,获取结果集
ResultSet resultSet = preparedStatement.executeQuery();

// 4. 遍历结果集,直接处理每个对象
while (resultSet.next()) {
// 创建一个新的Employee对象
Employee employee = new Employee();

// 从结果集中获取数据,并设置到Employee对象中
int empId = resultSet.getInt("emp_id");
String empName = resultSet.getString("emp_name");
Double empSalary = Double.valueOf(resultSet.getString("emp_salary"));
int empAge = resultSet.getInt("emp_age");

employee.setEmpId(empId);
employee.setEmpName(empName);
employee.setEmpSalary(empSalary);
employee.setEmpAge(empAge);

// 直接打印当前Employee对象
System.out.println(employee);
}

// 5. 释放资源
resultSet.close();
preparedStatement.close();
connection.close();
}

优点

  • 代码简单,不需要额外的数据结构(如List)。
  • 适合只需要打印或简单处理数据的场景。

缺点

  • 无法保存对象:每次循环处理完一个对象后,对象就会被丢弃,无法在后续代码中再次使用。
  • 不够灵活:如果需要对所有对象进行统一操作(如排序、筛选等),这种方式无法实现。
方式 2:使用数组(不推荐)

如果你不想用List,但又想保存多个对象,可以使用数组。不过,数组的长度是固定的,需要提前知道查询结果的数量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@Test
public void testORMWithArray() throws Exception {
// 1. 获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///xy", "root", "230320");

// 2. 创建PreparedStatement对象,预编译SQL
PreparedStatement preparedStatement = connection.prepareStatement("select emp_id, emp_name, emp_salary, emp_age from t_emp");

// 3. 执行查询,获取结果集
ResultSet resultSet = preparedStatement.executeQuery();

// 4. 获取结果集的行数(需要先遍历一次结果集)
resultSet.last(); // 将光标移动到最后一行
int rowCount = resultSet.getRow(); // 获取行数
resultSet.beforeFirst(); // 将光标移动回第一行之前

// 5. 创建一个数组,用于存储Employee对象
Employee[] employees = new Employee[rowCount];

// 6. 遍历结果集,将数据存储到数组中
int index = 0;
while (resultSet.next()) {
Employee employee = new Employee();
employee.setEmpId(resultSet.getInt("emp_id"));
employee.setEmpName(resultSet.getString("emp_name"));
employee.setEmpSalary(Double.valueOf(resultSet.getString("emp_salary")));
employee.setEmpAge(resultSet.getInt("emp_age"));

employees[index] = employee; // 将对象存入数组
index++;
}

// 7. 遍历数组,打印每个Employee对象
for (Employee emp : employees) {
System.out.println(emp);
}

// 8. 释放资源
resultSet.close();
preparedStatement.close();
connection.close();
}

优点

  • 可以保存多个对象,后续可以统一操作。

缺点

  • 数组长度固定:需要提前知道查询结果的数量,不够灵活。
  • 代码复杂:需要额外处理结果集的行数,增加了代码的复杂度。

官方解释

为什么不用List也可以打印多个对象?

在Java中,List是一种动态集合,用于存储多个对象。如果不使用List,可以通过循环直接处理每个对象,或者使用数组来存储对象。然而,这种方式通常不够灵活,尤其是在处理不确定数量的数据时。

为什么要用List

List是Java集合框架中的一种动态数据结构,支持动态扩容和丰富的操作方法。通过使用List,可以更方便地存储和管理多个对象,尤其是在需要对数据进行统一操作(如遍历、排序、筛选等)时。

为什么不推荐用数组?

数组的长度是固定的,无法动态扩容。在处理数据库查询结果时,查询结果的数量通常是不确定的,因此使用数组会导致代码复杂且不够灵活。相比之下,List可以动态调整大小,更适合处理不确定数量的数据。


总结

  • 不用List也可以打印多个对象:可以在循环中直接处理每个对象,或者使用数组。
  • 推荐使用ListList更灵活、更强大,适合处理不确定数量的数据。
  • 数组的局限性:数组长度固定,不够灵活,不适合处理动态数据。