我认为我遇到了一个非常直接的问题,但我无法为 Hibernate 的类提供一个好的结构或找到最佳实践的示例。
我有一个带有映射类测试的表测试。在一个由 bean 控制的页面上,我在一个列表中列出了所有项目以进行管理编辑(AdminTest),在另一个页面中列出了相同的项目,但对于普通用户来说,它们可以通过单选按钮来影响它们(ShowTest)而无需更改数据库。
由于 Hibernate 似乎坚持在您使用 addEntity 函数检索项目时指定一个直接映射的类(在我的以 Manager 结尾的类中),感觉就像我被迫做这样的事情:
class Test { ... }
class AdminTest extends Test { ... }
@ManagedBean
class AdminTestManager {
List<AdminTest> items;
}
class ShowTest extends Test { ... }
@ManagedBean
class ShowTestManager {
List<ShowTest> items;
}
然后将 AdminTest 和 ShowTest 分别映射到具有相同字段的同一个表。这真的很糟糕,因为每当我将字段添加到表测试时,我都需要更新这两个映射。
感觉就像我在这里遗漏了一些东西,你真的应该只需要一个 Test 映射到表 test 然后有一些漂亮的继承映射,但那些需要一些标识符,如列或一对一映射表。
编辑:
我尝试过的另一个解决方案是为 Test 提供一个映射,仍然让 AdminTest 和 ShowTest 扩展该类,但我正在将带有反射的 getter 复制到扩展类。
编辑2:
我将在这里提供一个“真实世界”的场景,以更好地解释我在问什么。假设我想制作一个测验引擎,其中有一页您可以通过输入字段填写问题,而另一页则通过每个项目的单选按钮列出这些问题,只有“是”或“否”。
数据库表将像这样创建:
CREATE TABLE question (id INT AUTO_iNCREMENT, text VARCHAR, correct_answer INT, primary key(id));
我认为我需要的课程是:
class Question {
private int id;
private String text;
private int correctAnswer;
// Getters and setters.
}
class EditQuestion extends Question {
void updateItem() { ... }
void removeItem() { ... }
}
@ManagedBean(name = "edit_quiz")
@ViewScoped
class EditQuestionManager {
List<EditQuestion> items;
void addItem() { ... }
void init() {
items = (ArrayList<EditQuestion>) HibernateUtil.getSessionFactory().getCurrentSession().createSQLQuery("SELECT * FROM question").addEntity(EditQuestion.class)
.list();
}
}
class AnswerQuestion extends Question {
int radioButtonValue;
// Getters and setters.
}
@ManagedBean(name = "take_quiz")
@ViewScoped
class AnswerQuestionManager {
List<AnswerQuestion> items;
void calculateResults() { ... }
void init() {
items = (ArrayList<AnswerQuestion>) HibernateUtil.getSessionFactory().getCurrentSession().createSQLQuery("SELECT * FROM question").addEntity(AnswerQuestion.class).list();
}
}
例如,显示测验的 JSF 页面可能是这样的:
<ui:repeat value="#{take_quiz.items}" var="question">
<div>#{question.text}</div>
<h:selectOneRadio value="#{question.radioButtonValue}" onchange="submit()">
<f:selectItem itemValue="1" itemLabel="Yes" />
<f:selectItem itemValue="0" itemLabel="No" />
</h:selectOneRadio>
</ui:repeat>
<h:commandLink action="#{take_quiz.calculateResults()}">Done</h:commandLink>
现在的问题,至少在我看来,是要为管理视图和用户视图制作这种列表,我需要输入条目以将表“问题”映射到 AnswerQuestion 和 EditQuestion hbm.xml 文件。至少不使用反射(将所有 getter 值从 Question 复制到 AnswerQuestion/EditQuestion 的新实例),这对我来说有点像 hack?我的意思是这似乎不太复杂?
解决方案:我没有让这些类扩展映射的 Hibernate 表类,而是简单地添加了它们类型的私有属性。同样在管理器类中,我在检索到数据库项目后循环访问它们并设置如下列表:
ArrayList<Question> tempItems = (ArrayList<Question>) HibernateUtil.getSessionFactory().getCurrentSession().createSQLQuery("SELECT * FROM question").addEntity(Question.class).list();
ArrayList<EditQuestion> items = ArrayList<EditQuestion>();
for(int i = 0; tempItems.size(); i++) {
EditQuestion item = new EditQuestion();
item.setQuestion(tempItems.get(i));
items.add(item);
}