简体   繁体   中英

JSF backing bean and Hibernate mapping

I've got a pretty straight-forward problem I think but I couldn't come up with a nice structure for the classes with Hibernate or find examples of best practices.

I've got one table test with a mapped class Test. On one page controlled by a bean I've got all the items in a list for administrative editing (AdminTest) and in another page the same items are listed but for normal users with things like radio-buttons to influence them (ShowTest) without altering the database.

Since Hibernate seem to insist that you specify a directly mapped class when you retrieve items with the addEntity-function (in my classes ending with Manager) it feels like I'm forced to do something like this:

class Test { ... }

class AdminTest extends Test { ... }

@ManagedBean
class AdminTestManager {

    List<AdminTest> items;

}

class ShowTest extends Test { ... }

@ManagedBean
class ShowTestManager {

    List<ShowTest> items;

}

Then have separate mapping for both AdminTest and ShowTest to the same table with the same fields. This is really bad since I need to update both mappings whenever I add a field to the table test.

It feels like I've missed something here, that you should really just need the one Test mapped to the table test then have some pretty inheritance mapping but those require some identifier like a column or one-to-one mapped table.

EDIT:

Another solution I've tried was having one mapping for Test, still having AdminTest and ShowTest extend that class, but I'm copying the getters with reflection to the extended classes.

EDIT 2:

I'll provide a "real world" scenario here to better explain what I'm asking. Lets say I want to make a quiz-engine with one page where you can fill in questions through input-fields and another which lists these questions with a radio-button by each item with just "yes" or "no".

The database-table would just be created like this:

CREATE TABLE question (id INT AUTO_iNCREMENT, text VARCHAR, correct_answer INT, primary key(id));

The classes that I think I would need are these:

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();

        }
}

Then for example the JSF-page displaying the quiz could be something like this:

<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>

Now the problem, at-least as it appears to me, is that to make this sort of list for both the admin-view and user-view I need to make entries to map the table "question" to both AnswerQuestion and EditQuestion in the hbm.xml-file. At-least without using reflection (to copy all the getter-values from Question to a new instance of AnswerQuestion/EditQuestion) which sort of feel like a hack to me? I mean this doesn't seem too complicated?

SOLUTION: Instead of having the classes extend the mapped Hibernate-table classes I simply added a private property of their types. Also in the Manager-classes I loop through the items from the database after they've been retrieved and set the lists like this:

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);
}

I'm struggling to understand your question. Are you having trouble expressing Class inheritance for entities?

Have you considered using the import javax.persistence.Inheritance annotation on top of your Test class?

Example:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Test {
}

@Entity
public class AdminTest extends Test {
}

More here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM