如何将表映射到 Java 个对象
How do I map tables to Java objects
举个例子,我有三个这样的 table。
database image
我如何将第三个 table 映射到 java 对象。
class StudentCourse{
Student student;
Course course;
Double score;
}
或
class StudentCourse{
Long studentId;
Long courseId;
Double score;
}
如果我使用第一个,在我更新数据库中的一些数据后,例如学生 informations.The 下次我从数据库中查询 StudentCourse(我使用 mybatis)时,缓存会导致数据不正确吗?
如果我使用第二个,如果我想列出学生的课程分数,我必须首先查询 StudentCourse 列表,然后通过 courseId 从数据库中查询课程信息,对于每个结果我需要额外的查询。我认为那会降低程序的效率。
还有其他方法可以解决这个问题吗?
对于第一个。
mybatis第二次查询,如果数据还没有更新,就从缓存中获取结果。
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
this.localCache.putObject(key, ExecutionPlaceholder.EXECUTION_PLACEHOLDER);
List list;
try {
list = this.doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
this.localCache.removeObject(key);
}
this.localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
this.localOutputParameterCache.putObject(key, parameter);
}
return list;
}
如果我有这样的 resultMap
<resultMap id="studentcourse" type="StudentCourse">
<association property="student" resultMap="Student" />
<association property="course" resultMap="Course"/>
<result property="score" column="score"/>
</resultMap>
首先我从数据库中获取一个 StudentCourse 对象,localCache 缓存 object.And 然后我更新 StudentCourse 中的课程(更改数据库记录)。第二次我获取一些 StudentCourse 它将 return一个结果localcache.So StudentCourse里面的课程信息是脏的data.How如果我选择第一个就处理它。
理想情况下,您会使用最能为您的域建模的 class 设计,并担心映射到单独持久层中的数据存储。如果您需要大幅更改模型以允许持久层运行,那么您需要一个新的 ORM!虽然我不熟悉 mybatis,但我希望它不会在每次更改基础数据时都创建一个新对象。
course
和 student
table 中的键充当 student_course
table 中的外键。外键最好表示为 Java 中的引用。在 Java 级别使用密钥会强制执行额外的间接级别,并使您面临完整性问题(例如,如果外键更改)。
所以我建议:
class StudentCourse {
private final Student student;
private final Course course;
private double score;
}
您也可以考虑将它放在其他 classes 之一中 - 这可能更方便,具体取决于 classes 的使用方式:
class Student {
private final int id;
private String name;
private List<CourseScores> scores = new ArrayList<>();
public void addCourseScore(Course course, double score) {
scores.add(new CourseScore(course, score));
}
private record CourseScores(Course course, double score) { };
}
如果您的 ORM 不为您解析键(即在检索数据时自动查找引用的对象),那么您需要自己做。然而,这是一个非常简单的对象:
class College {
private Map<Integer,Student> students;
private Map<Integer,Course> courses;
}
因此将 student_course
数据转换为上述模型的代码可能如下所示:
ResultSet data;
while (!data.isAfterLast()) {
Student student = college.getStudent(data.getInteger("student"));
Course course = college.getCourse(data.getInteger("course"));
double score = data.getDouble("score");
student.addCourseScore(course, score);
data.next();
}
举个例子,我有三个这样的 table。 database image 我如何将第三个 table 映射到 java 对象。
class StudentCourse{
Student student;
Course course;
Double score;
}
或
class StudentCourse{
Long studentId;
Long courseId;
Double score;
}
如果我使用第一个,在我更新数据库中的一些数据后,例如学生 informations.The 下次我从数据库中查询 StudentCourse(我使用 mybatis)时,缓存会导致数据不正确吗? 如果我使用第二个,如果我想列出学生的课程分数,我必须首先查询 StudentCourse 列表,然后通过 courseId 从数据库中查询课程信息,对于每个结果我需要额外的查询。我认为那会降低程序的效率。 还有其他方法可以解决这个问题吗?
对于第一个。 mybatis第二次查询,如果数据还没有更新,就从缓存中获取结果。
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
this.localCache.putObject(key, ExecutionPlaceholder.EXECUTION_PLACEHOLDER);
List list;
try {
list = this.doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
this.localCache.removeObject(key);
}
this.localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
this.localOutputParameterCache.putObject(key, parameter);
}
return list;
}
如果我有这样的 resultMap
<resultMap id="studentcourse" type="StudentCourse">
<association property="student" resultMap="Student" />
<association property="course" resultMap="Course"/>
<result property="score" column="score"/>
</resultMap>
首先我从数据库中获取一个 StudentCourse 对象,localCache 缓存 object.And 然后我更新 StudentCourse 中的课程(更改数据库记录)。第二次我获取一些 StudentCourse 它将 return一个结果localcache.So StudentCourse里面的课程信息是脏的data.How如果我选择第一个就处理它。
理想情况下,您会使用最能为您的域建模的 class 设计,并担心映射到单独持久层中的数据存储。如果您需要大幅更改模型以允许持久层运行,那么您需要一个新的 ORM!虽然我不熟悉 mybatis,但我希望它不会在每次更改基础数据时都创建一个新对象。
course
和 student
table 中的键充当 student_course
table 中的外键。外键最好表示为 Java 中的引用。在 Java 级别使用密钥会强制执行额外的间接级别,并使您面临完整性问题(例如,如果外键更改)。
所以我建议:
class StudentCourse {
private final Student student;
private final Course course;
private double score;
}
您也可以考虑将它放在其他 classes 之一中 - 这可能更方便,具体取决于 classes 的使用方式:
class Student {
private final int id;
private String name;
private List<CourseScores> scores = new ArrayList<>();
public void addCourseScore(Course course, double score) {
scores.add(new CourseScore(course, score));
}
private record CourseScores(Course course, double score) { };
}
如果您的 ORM 不为您解析键(即在检索数据时自动查找引用的对象),那么您需要自己做。然而,这是一个非常简单的对象:
class College {
private Map<Integer,Student> students;
private Map<Integer,Course> courses;
}
因此将 student_course
数据转换为上述模型的代码可能如下所示:
ResultSet data;
while (!data.isAfterLast()) {
Student student = college.getStudent(data.getInteger("student"));
Course course = college.getCourse(data.getInteger("course"));
double score = data.getDouble("score");
student.addCourseScore(course, score);
data.next();
}