LINUX.ORG.RU

JSF и Hibernate

 , ,


1

2

У меня есть некая сущность (модель):

@Entity
@Table(name ="task")
public class Task {
    Integer id;
    String name;
    Date start;
    Date end;
    // и тд.
    // ну и соответствующие сеттеры и геттеры тоже присутствуют
}
Есть DAO, интерфейс выглядит так:
public interface TaskDAO {
    public void addTask(Task Task) throws SQLException;
    public void updateTask(Task Task) throws SQLException;
    public Task getTaskById(Long id) throws SQLException;
    public List getAllTasks() throws SQLException;
    public void deleteTask(Task Task) throws SQLException;
}
Ну и его реализация:
public class TaskDAOImpl implements TaskDAO {

    public void addTask(Task task) throws SQLException {
        Session session = null;
        try {
            session = HibernateUtil.getSession();
            session.beginTransaction();
            session.save(task);
            session.getTransaction().commit();
        } catch (Exception e) {
            System.out.print("Error");
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
    }
    // и тд
}

Теперь я хочу сделать возможность добавления в БД, данные будут браться из формы. Представление надо реализовать на JSF. Я сделал бин следующего вида:

@ManagedBean(name = "addTaskBean", eager=true)
@RequestScoped
public class AddTaskBean {

    Task task;

    public Task getTask() {
        return task;
    }

    //@PostConstruct
    //public void init() { 
    //    task = new Task();
    //}

    public String add() throws SQLException {
        //task = new Task();
        Factory.getInstance().getTaskDAO().addTask(task);
        return "index";
    }
}
Ну и jsf-файл
<h:form>
    <h:panelGrid columns="2">
        <h:outputLabel value="Имя" for="id_name"/>
        <h:inputText id="id_name" value="#{addTaskBean.task.name}"/>
        <!-- и тд -->
    </h:panelGrid>    
    <h:commandLink action="#{addTaskBean.add}" value="Добавить"/>
</h:form>
Вот тут и начинается проблема: если раскомментить эти строчки
@PostConstruct
public void init() { 
    task = new Task();
}
То при нажатии на кнопку происходит нифига. Есть раскомментить эту строчку:
task = new Task();
То возникает ошибка:
javax.el.PropertyNotFoundException: /resources/components/gantt/addTask.xhtml @18,73 value="#{addTaskBean.task.name}": Target Unreachable, 'null' returned null

Что делать? Есть ли примеры использования JSF с Hibernate. При этом, мне надо отделить бин от сущности. Т.е. в одном классе будет описываться модель, а в другом классе будет контроллер, который будет добавлять экземпляр в БД и связываться с кнопкой.


Ты в спринге или Java EE?

1) Умоляют тебя, не управляй транзакциями руками. @Transactional в помощь

2) «Нифига» - понятие растяжимое. Что ты хочешь чтобы происходило? У тебя в базе строка не добавляется?

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

EE, спринг не использую.

1) не понял, поясни пожалуйста. делал по примерам. там везде так.

2) ну вообще ничего. в БД ничего нового не появляется, страница остаётся ровно той же. Даже если в конце метода add вернуть «index», перенаправления не происходит.

memnek
() автор топика
Ответ на: комментарий от vertexua

EE 7-я. Список вывожу так: в ДАО есть метод getAllTasks, который возвращает список задач. Ещё есть бин TasksBean, который выглядит так:

@ManagedBean
class TasksBean {
   public List<Task> getTasks() {
        Fabric.getInstance().getTaskDAO().getAllTasks();
   }
}
ну и в jsf получаю список так:
<ui:repeat value="#{tasksBean.tasks}" var="t"/>

memnek
() автор топика
Ответ на: комментарий от memnek

У тебя код себя странно ведет. В любом случае, обычно

1) Используют JPA. Java EE все-таки

2) Пишут репозиторий - @Stateless класс, в котором делаются базовые операции над данными. Не больше одного запроса на метод. @Stateless обозначает EJB, который автоматически управляет транзакциями

3) Логика по сложнее пишется в сервисе. То же самое что и в пункте 2), но пользуется репозиторием, иногда выполняет запросы сам, но логика методов более сложная

4) В бины JSF подключают уже репозитории или сервисы.

5) Для внедрения зависимостей используют @Inject. man CDI

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

1) я хотел хибернейт.

2) в примерах по JSF делают так: создают бин, в котором описывают поля модели, а потом создают методы getTask, addTask, в которых делают работу с БД. Либо создают сущность, Facet-класс для неё и делают методы CRUD (это на сайте нетбинса). Я хотел сделать так: есть модель и ДАО для работы с ней. А в бинах я бы просто вызывал методы из ДАО. для списка всё норм. а вот при создании возникают проблемы. короче, надо как-то при пост-запросе создать таск с пустым конструктором, а JSF сам бы заполнял поля из форм. при этом, в бине было бы просто поле моей модели: http://stackoverflow.com/questions/10301363/jpa-entity-as-jsf-bean

можно конечно взять пример из туториалов нетбинса. переписывать просто не оч хочется. я хотел сделать разделение: модель + ДАО для операций с БД, JSF + бин для вывода/ввода инфы.

memnek
() автор топика
Последнее исправление: memnek (всего исправлений: 1)
Ответ на: комментарий от memnek

я хотел хибернейт.

Тебе не страшно его пихать в Classpath чтобы потом он смешался в Hibernate, который реализация стандарта JPA например в JBoss?

Пользуйся лучше Hibernate через JPA

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

вроде переделал, использую JPA с поставщиком в виде Hibernate.

Теперь вылезли проблемы в виде NullPointerException при работе EntityManager'a. У меня есть сущность (почти не изменилась), класс TaskFacade:

@Stateless
public class TaskFacade {
    @PersistenceContext(unitName = "TaskPU")
    private EntityManager em; // это поле всегда null

    public List<Task> findAll() {
        CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
        cq.select(cq.from(Task.class));
        return em.createQuery(cq).getResultList();
    }
}
И контроллер:
@ManagedBean(name = "taskController")
@SessionScoped
public class TaskController {

    private Task current;

    @EJB
    private TaskFacadeLocal ejbFacade;

    public List<Task> getTasks() {
        return ejbFacade.findAll();
    }
конфиг БД
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">

    <persistence-unit name="TaskPU">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>jgantt.jpa.entities.Task</class>
        <properties>
            <property name="hibernate.connection.url" value="jdbc:sqlite:/path/to/db.db"/>
            <property name="hibernate.connection.driver_class" value="org.sqlite.JDBC"/>
            <property name="hibernate.dialect" value="jgantt.jpa.util.SQLiteDialect"/>
            <property name="hibernate.connection.username" value=""/>
            <property name="hibernate.connection.password" value=""/>
            <property name="hibernate.archive.autodetection" value="class"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>
</persistence>
Проблема в том, что при вызове findAll возникает NPE, потому что em == null.

Читал, что надо модифицировать класс TaskFacade, чтобы он стал управляемым (managed) или настроить правильно БД. Однако что-то ничего не вышло, либо я делал что-то не то. Не подскажешь, как решить эту проблему?

memnek
() автор топика
Последнее исправление: memnek (всего исправлений: 1)
Ответ на: комментарий от vertexua

Тебе не страшно его пихать в Classpath

если хочется самого распоследнего хибернейта, то иначе и не получится

stevejobs ★★★★☆
()
Ответ на: комментарий от memnek

Почему то не заинжектился энтитиманагер, внимательно смотри логи сервера, т.к. он либо не смог создаться, либо не смог заинжетиться, в любом случае в лог бы посыпались ошибки. С виду всё корректно.

ya-betmen ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.