Как мы можем разрешить отношения многие ко многим через страницу JSF, используя Netbeans? - PullRequest
1 голос
/ 14 февраля 2012

Использовал простую базу данных InnoDB MySQL (отношения между многими между WRITER и FORUM и таблицу соединений с именем writer_forum) в Netbeans 7.1 и создал веб-приложение Java EE 6, работающее под управлением Glassfish 3.1 Open Source Edition. Другие платформы не используются, кроме JSF 2.0

  • Сгенерированные сущности из базы данных (с использованием EclipseLink (JPA 2.0), и все выглядит нормально, насколько я могу судить, код в сущностях верен.
  • Сгенерированные страницы JSF из сущностей (IDE генерирует EJB-сеансные компоненты, управляемые компоненты и страницы JSF с использованием facelets .xhtml).

Поддерживаются все отношения, кроме MANY TO MANY. Кто-нибудь имел такой же опыт и сумел включить поддержку отношений «Многие ко многим»?

package entities;

@Entity
@Table(name = "writer")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Writer.findAll", query = "SELECT w FROM Writer w"),
    @NamedQuery(name = "Writer.findByWriterid", query = "SELECT w FROM Writer w WHERE w.writerid = :writerid"),
    @NamedQuery(name = "Writer.findByName", query = "SELECT w FROM Writer w WHERE w.name = :name"),
    @NamedQuery(name = "Writer.findBySurname", query = "SELECT w FROM Writer w WHERE w.surname = :surname"),
    @NamedQuery(name = "Writer.findByField", query = "SELECT w FROM Writer w WHERE w.field = :field")})
public class Writer implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @NotNull
    @Column(name = "writerid")
    private Integer writerid;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 45)
    @Column(name = "name")
    private String name;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 45)
    @Column(name = "surname")
    private String surname;
    @Size(max = 45)
    @Column(name = "field")
    private String field;
    @ManyToMany(mappedBy = "writerCollection")
    private Collection<Forum> forumCollection;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "writer")
    private Collection<Book> bookCollection;

    public Writer() {
    }

    public Writer(Integer writerid) {
        this.writerid = writerid;
    }

    public Writer(Integer writerid, String name, String surname) {
        this.writerid = writerid;
        this.name = name;
        this.surname = surname;
    }

    public Integer getWriterid() {
        return writerid;
    }

    public void setWriterid(Integer writerid) {
        this.writerid = writerid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    @XmlTransient
    public Collection<Forum> getForumCollection() {
        return forumCollection;
    }

    public void setForumCollection(Collection<Forum> forumCollection) {
        this.forumCollection = forumCollection;
    }

    @XmlTransient
    public Collection<Book> getBookCollection() {
        return bookCollection;
    }

    public void setBookCollection(Collection<Book> bookCollection) {
        this.bookCollection = bookCollection;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (writerid != null ? writerid.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Writer)) {
            return false;
        }
        Writer other = (Writer) object;
        if ((this.writerid == null && other.writerid != null) || (this.writerid != null && !this.writerid.equals(other.writerid))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return name + " | " + writerid;
    }

}

-------- ФОРУМ JPA-сущность

 @Entity
    @Table(name = "forum")
    @XmlRootElement
    @NamedQueries({
        @NamedQuery(name = "Forum.findAll", query = "SELECT f FROM Forum f"),
        @NamedQuery(name = "Forum.findByForumid", query = "SELECT f FROM Forum f WHERE f.forumid = :forumid"),
        @NamedQuery(name = "Forum.findByLabel", query = "SELECT f FROM Forum f WHERE f.label = :label")})
    public class Forum implements Serializable {
        private static final long serialVersionUID = 1L;
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Basic(optional = false)
        @NotNull
        @Column(name = "forumid")
        private Integer forumid;
        @Size(max = 45)
        @Column(name = "label")
        private String label;
        @JoinTable(name = "forum_writer", joinColumns = {
            @JoinColumn(name = "forum_forumid", referencedColumnName = "forumid")}, inverseJoinColumns = {
            @JoinColumn(name = "writer_writerid", referencedColumnName = "writerid")})
        @ManyToMany
        private Collection<Writer> writerCollection;

        public Forum() {
        }

        public Forum(Integer forumid) {
            this.forumid = forumid;
        }

        public Integer getForumid() {
            return forumid;
        }

        public void setForumid(Integer forumid) {
            this.forumid = forumid;
        }

        public String getLabel() {
            return label;
        }

        public void setLabel(String label) {
            this.label = label;
        }

        @XmlTransient
        public Collection<Writer> getWriterCollection() {
            return writerCollection;
        }

        public void setWriterCollection(Collection<Writer> writerCollection) {
            this.writerCollection = writerCollection;
        }

        @Override
        public int hashCode() {
            int hash = 0;
            hash += (forumid != null ? forumid.hashCode() : 0);
            return hash;
        }

        @Override
        public boolean equals(Object object) {
            // TODO: Warning - this method won't work in the case the id fields are not set
            if (!(object instanceof Forum)) {
                return false;
            }
            Forum other = (Forum) object;
            if ((this.forumid == null && other.forumid != null) || (this.forumid != null && !this.forumid.equals(other.forumid))) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return "entities.Forum[ forumid=" + forumid + " ]";
        }

    }

Фасад Асбракт

 public abstract class AbstractFacade<T> {
        private Class<T> entityClass;

        public AbstractFacade(Class<T> entityClass) {
            this.entityClass = entityClass;
        }

        protected abstract EntityManager getEntityManager();

        public void create(T entity) {
            getEntityManager().persist(entity);
        }

        public void edit(T entity) {
            getEntityManager().merge(entity);
        }

        public void remove(T entity) {
            getEntityManager().remove(getEntityManager().merge(entity));
        }

        public T find(Object id) {
            return getEntityManager().find(entityClass, id);
        }

        public List<T> findAll() {
            javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
            cq.select(cq.from(entityClass));
            return getEntityManager().createQuery(cq).getResultList();
        }

        public List<T> findRange(int[] range) {
            javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
            cq.select(cq.from(entityClass));
            javax.persistence.Query q = getEntityManager().createQuery(cq);
            q.setMaxResults(range[1] - range[0]);
            q.setFirstResult(range[0]);
            return q.getResultList();
        }

        public int count() {
            javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
            javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
            cq.select(getEntityManager().getCriteriaBuilder().count(rt));
            javax.persistence.Query q = getEntityManager().createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        }

    }

Фасад форума

@Stateless
public class ForumFacade extends AbstractFacade<Forum> {
    @PersistenceContext(unitName = "writerPU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public ForumFacade() {
        super(Forum.class);
    }

}

------------- Управляемый компонент

 @ManagedBean(name = "writerController")
    @SessionScoped
    public class WriterController implements Serializable {

        private Writer current;
        private DataModel items = null;
        @EJB
        private session.WriterFacade ejbFacade;
        private PaginationHelper pagination;
        private int selectedItemIndex;

        public WriterController() {
        }

        public Writer getSelected() {
            if (current == null) {
                current = new Writer();
                selectedItemIndex = -1;
            }
            return current;
        }

        private WriterFacade getFacade() {
            return ejbFacade;
        }

        public PaginationHelper getPagination() {
            if (pagination == null) {
                pagination = new PaginationHelper(10) {

                    @Override
                    public int getItemsCount() {
                        return getFacade().count();
                    }

                    @Override
                    public DataModel createPageDataModel() {
                        return new ListDataModel(getFacade().findRange(new int[]{getPageFirstItem(), getPageFirstItem() + getPageSize()}));
                    }
                };
            }
            return pagination;
        }

        public String prepareList() {
            recreateModel();
            return "List";
        }

        public String prepareView() {
            current = (Writer) getItems().getRowData();
            selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
            return "View";
        }

        public String prepareCreate() {
            current = new Writer();
            selectedItemIndex = -1;
            return "Create";
        }

        public String create() {
            try {
                getFacade().create(current);
                JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("WriterCreated"));
                return prepareCreate();
            } catch (Exception e) {
                JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
                return null;
            }
        }

        public String prepareEdit() {
            current = (Writer) getItems().getRowData();
            selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
            return "Edit";
        }

        public String update() {
            try {
                getFacade().edit(current);
                JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("WriterUpdated"));
                return "View";
            } catch (Exception e) {
                JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
                return null;
            }
        }

        public String destroy() {
            current = (Writer) getItems().getRowData();
            selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
            performDestroy();
            recreatePagination();
            recreateModel();
            return "List";
        }

        public String destroyAndView() {
            performDestroy();
            recreateModel();
            updateCurrentItem();
            if (selectedItemIndex >= 0) {
                return "View";
            } else {
                // all items were removed - go back to list
                recreateModel();
                return "List";
            }
        }

        private void performDestroy() {
            try {
                getFacade().remove(current);
                JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("WriterDeleted"));
            } catch (Exception e) {
                JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
            }
        }

        private void updateCurrentItem() {
            int count = getFacade().count();
            if (selectedItemIndex >= count) {
                // selected index cannot be bigger than number of items:
                selectedItemIndex = count - 1;
                // go to previous page if last page disappeared:
                if (pagination.getPageFirstItem() >= count) {
                    pagination.previousPage();
                }
            }
            if (selectedItemIndex >= 0) {
                current = getFacade().findRange(new int[]{selectedItemIndex, selectedItemIndex + 1}).get(0);
            }
        }

        public DataModel getItems() {
            if (items == null) {
                items = getPagination().createPageDataModel();
            }
            return items;
        }

        private void recreateModel() {
            items = null;
        }

        private void recreatePagination() {
            pagination = null;
        }

        public String next() {
            getPagination().nextPage();
            recreateModel();
            return "List";
        }

        public String previous() {
            getPagination().previousPage();
            recreateModel();
            return "List";
        }

        public SelectItem[] getItemsAvailableSelectMany() {
            return JsfUtil.getSelectItems(ejbFacade.findAll(), false);
        }

        public SelectItem[] getItemsAvailableSelectOne() {
            return JsfUtil.getSelectItems(ejbFacade.findAll(), true);
        }

        @FacesConverter(forClass = Writer.class)
        public static class WriterControllerConverter implements Converter {

            public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
                if (value == null || value.length() == 0) {
                    return null;
                }
                WriterController controller = (WriterController) facesContext.getApplication().getELResolver().
                        getValue(facesContext.getELContext(), null, "writerController");
                return controller.ejbFacade.find(getKey(value));
            }

            java.lang.Integer getKey(String value) {
                java.lang.Integer key;
                key = Integer.valueOf(value);
                return key;
            }

            String getStringKey(java.lang.Integer value) {
                StringBuffer sb = new StringBuffer();
                sb.append(value);
                return sb.toString();
            }

            public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
                if (object == null) {
                    return null;
                }
                if (object instanceof Writer) {
                    Writer o = (Writer) object;
                    return getStringKey(o.getWriterid());
                } else {
                    throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + WriterController.class.getName());
                }
            }
        }
    }

---------- XTMLCreate PAGE для WRITER ---- **

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <ui:composition template="/template.xhtml">
        <ui:define name="title">
            <h:outputText value="#{bundle.CreateWriterTitle}"></h:outputText>
        </ui:define>
        <ui:define name="body">
            <h:panelGroup id="messagePanel" layout="block">
                <h:messages errorStyle="color: red" infoStyle="color: green" layout="table"/>
            </h:panelGroup>
            <h:form>
                <h:panelGrid columns="2">
                    <h:outputLabel value="#{bundle.CreateWriterLabel_writerid}" for="writerid" />
                    <h:inputText id="writerid" value="#{writerController.selected.writerid}" title="#{bundle.CreateWriterTitle_writerid}" required="true" requiredMessage="#{bundle.CreateWriterRequiredMessage_writerid}"/>
                    <h:outputLabel value="#{bundle.CreateWriterLabel_name}" for="name" />
                    <h:inputText id="name" value="#{writerController.selected.name}" title="#{bundle.CreateWriterTitle_name}" required="true" requiredMessage="#{bundle.CreateWriterRequiredMessage_name}"/>
                    <h:outputLabel value="#{bundle.CreateWriterLabel_surname}" for="surname" />
                    <h:inputText id="surname" value="#{writerController.selected.surname}" title="#{bundle.CreateWriterTitle_surname}" required="true" requiredMessage="#{bundle.CreateWriterRequiredMessage_surname}"/>
                    <h:outputLabel value="#{bundle.CreateWriterLabel_field}" for="field" />
                    <h:inputText id="field" value="#{writerController.selected.field}" title="#{bundle.CreateWriterTitle_field}" />
                </h:panelGrid>
                <br />
                <h:commandLink action="#{writerController.create}" value="#{bundle.CreateWriterSaveLink}" />
                <br />
                <br />
                <h:commandLink action="#{writerController.prepareList}" value="#{bundle.CreateWriterShowAllLink}" immediate="true"/>
                <br />
                <br />
                <h:commandLink value="#{bundle.CreateWriterIndexLink}" action="/index" immediate="true" />
            </h:form>
        </ui:define>
    </ui:composition>
</html>

**

...