Vaadin JPAContainer和Tree拖放

时间:2014-09-08 06:34:06

标签: java jpa drag-and-drop tree vaadin

我有一个带有创作者(作者)层次结构的有声读物数据库。我使用父ID作为关系。如果我的作者的名字拼写不同,我会将其作为拼写正确的作者的孩子。我使用JPA创建和访问数据库。 我在Tree UI中加载JPAContainer并且可以正常工作。 但是当我将一个Item拖放到另一个Item上时,拖动的Item将成为新创建的父项的子项,其中包含放置目标的名称。它不应该创建新的父级,而只需将子级添加到droptarget。 我在这里错过了什么?

Creator.java

@Entity
@Table(name = "creator")
@NamedQueries({
        @NamedQuery(name = "Creator.findAll", query = "SELECT c FROM Creator c"),
        @NamedQuery(name = "Creator.findByName", query = "SELECT c FROM  Creator c WHERE c.name = :name") })
public class Creator implements Serializable {
    private static final long serialVersionUID = 1L;

    @TableGenerator(name = "Creator_Gen", table = "ID_GEN", pkColumnName = "GEN_NAME", valueColumnName = "GEN_VAL", pkColumnValue = "Creator_Gen", initialValue = 1)
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "Creator_Gen")
    @Column(unique = true, nullable = false)
    private Integer id;

    @Column(length = 10000)
    private String bio;

    @Temporal(TemporalType.DATE)
    private Date birthdate;

    @Column(nullable = false, length = 50)
    private String name;

    // bi-directional many-to-one association to Book
    @OneToMany(mappedBy = "creator")
    private List<Book> books;

    // bi-directional many-to-one association to Nationality
    @ManyToOne(cascade = { CascadeType.PERSIST })
    @JoinColumn(name = "nationality")
    private Nationality nationality;

    @Transient
    private Boolean superCreator;

    @ManyToOne(targetEntity=model.Creator.class)
    @OrderBy("name")
    @JoinColumn(name="parent",referencedColumnName="id")  
    private Creator parent;

    @OneToMany(mappedBy="parent")
    @OrderBy("name")
    private List<Creator> children;

    public Creator() {
    }

    public Creator(String author) {
        this.name = author;
    }

    public Integer getId() {
        return this.id;
    }

Vaadin UI树代码BooksMain.java的一部分。

public BooksMainView() {
        JPAContainer<Creator> creators = new JPAContainer<Creator>(
                Creator.class) {
            private static final long serialVersionUID = 1L;

            @Override
            public boolean areChildrenAllowed(Object itemId) {
                return getItem(itemId).getEntity().getChildren().size() > 0;
            }
        };
        EntityManager em = JPAContainerFactory
                .createEntityManagerForPersistenceUnit(BookPersistenceManager.PERSISTENCE_UNIT);

        creators.setEntityProvider(new CachingLocalEntityProvider<Creator>(
                Creator.class, em));
        creators.setParentProperty("parent");

        buildTree();
    }

    private void buildTree() {
        groupTree = new Tree("creators", creators);
        groupTree.setItemCaptionMode(ItemCaptionMode.PROPERTY);
        groupTree.setItemCaptionPropertyId("id");
        groupTree.setImmediate(true);
        groupTree.setSelectable(true);
        groupTree.setDragMode(TreeDragMode.NODE);

        // Allow the tree to receive drag drops and handle them
        groupTree.setDropHandler(new DropHandler() {
            public AcceptCriterion getAcceptCriterion() {
                return AcceptAll.get();
            }

            public void drop(DragAndDropEvent event) {
                // Wrapper for the object that is dragged
                Transferable t = event.getTransferable();

                // Make sure the drag source is the same tree
                if (t.getSourceComponent() != groupTree)
                    return;

                AbstractSelectTargetDetails target = (AbstractSelectTargetDetails) event
                        .getTargetDetails();

                // Get ids of the dragged item and the target item
                Object sourceItemId = t.getData("itemId");
                Object targetItemId = target.getItemIdOver();

                // On which side of the target the item was dropped
                VerticalDropLocation location = target.getDropLocation();

                HierarchicalEntityContainer<Creator> container = (HierarchicalEntityContainer<Creator>) groupTree
                        .getContainerDataSource();

                EntityItem<Creator> src = container.getItem(sourceItemId);
                EntityItem<Creator> dst = container.getItem(targetItemId);

                // Drop right on an item -> make it a child
                if (location == VerticalDropLocation.MIDDLE) {
                    System.out.println("source:" + src.getItemProperty("name")
                            + " id:" + src.getItemProperty("id"));
                    System.out.println("target:" + dst.getItemProperty("name")
                            + " id:" + dst.getItemProperty("id"));

                    src.getItemProperty("parent").setValue(dst);
                } 
            }
        });
        setFirstComponent(groupTree);
    }

1 个答案:

答案 0 :(得分:0)

已经过了一段时间,但解决了这个问题。解决方案与DropHandler中的预期一致。您需要将属性&#34; parent&#34;设置为目标实体。

if (location == VerticalDropLocation.MIDDLE) {
                if (src.getItemId() != dst.getItemId()) {
                    src.getItemProperty("parent").setValue(dst.getEntity());
                    creators.refresh();
                }
            } else {
                src.getItemProperty("parent").setValue(null);
                creators.refresh();
            }

这里是完整的类源代码。

public class CreatorTree extends Tree {

private static final long serialVersionUID = 9071565734995148942L;
private HierarchicalCreatorContainer creators;
private Creator creatorFilter;
private SearchFilter filter;

private ArrayList<CreatorSelectionListener> mSelectionListeners;

public CreatorTree(HierarchicalCreatorContainer creators) {
    super("creators", creators);
    this.creators = creators;
    buildTree();
    this.mSelectionListeners = new ArrayList<CreatorSelectionListener>();
}

public CreatorTree(HierarchicalCreatorContainer creators,
        SearchFilter filter) {
    this(creators);
    this.filter = filter;
    filter.addCreatorContainer(creators);
}

private void buildTree() {
    setItemCaptionMode(ItemCaptionMode.PROPERTY);
    setItemCaptionPropertyId("name");
    // expand tree
    // for (Object rootId : creators.rootItemIds())
    // groupTree.expandItemsRecursively(rootId);
    setImmediate(true);
    setSelectable(true);
    setDragMode(TreeDragMode.NODE);

    addValueChangeListener(new Property.ValueChangeListener() {

        private static final long serialVersionUID = 1L;
        private Object prev_sel_id;

        @Override
        public void valueChange(
                com.vaadin.data.Property.ValueChangeEvent event) {
            Object id = event.getProperty().getValue();
            if (id != null) {
                Creator entity = creators.getItem(id).getEntity();
                if (entity.hasChildren()) {
                    expandItem(id);
                    if (prev_sel_id != null && prev_sel_id != id)
                        collapseItem(prev_sel_id);
                    prev_sel_id = id;
                }
                creatorFilter = entity;
                for (CreatorSelectionListener sl : mSelectionListeners) {
                    sl.creatorSelected(entity);
                }
            } else if (creatorFilter != null) {
                creatorFilter = null;
            }
            filter.updateFilters(creatorFilter);
        }
    });

    // Allow the tree to receive drag drops and handle them
    setDropHandler(new DropHandler() {

        private static final long serialVersionUID = -3077253259924255881L;

        public AcceptCriterion getAcceptCriterion() {
            return AcceptAll.get();
        }

        public void drop(DragAndDropEvent event) {
            // Wrapper for the object that is dragged
            Transferable t = event.getTransferable();
            AbstractSelectTargetDetails target = (AbstractSelectTargetDetails) event
                    .getTargetDetails();
            // Get ids of the dragged item and the target item
            Object sourceItemId = t.getData("itemId");
            Object targetItemId = target.getItemIdOver();

            // On which side of the target the item was dropped
            VerticalDropLocation location = target.getDropLocation();
            HierarchicalEntityContainer<Creator> container = (HierarchicalEntityContainer<Creator>) getContainerDataSource();
            EntityItem<Creator> src = container.getItem(sourceItemId);
            EntityItem<Creator> dst = container.getItem(targetItemId);
            System.out.println("source:" + src.getItemProperty("name")
                    + " id:" + src.getItemProperty("id"));
            System.out.println("target:" + dst.getItemProperty("name")
                    + " id:" + dst.getItemProperty("id"));
            // Drop right on an item -> make it a child
            if (location == VerticalDropLocation.MIDDLE) {
                if (src.getItemId() != dst.getItemId()) {
                    src.getItemProperty("parent").setValue(dst.getEntity());
                    creators.refresh();
                }
            } else {
                src.getItemProperty("parent").setValue(null);
                creators.refresh();
            }
        }
    });
}

public void refresh() {
    this.getUI().getSession().lock();
    try {
        creators.refresh();
    } finally {
        this.getUI().getSession().unlock();
    }

}

public void addSelectionListener(CreatorSelectionListener selectionlistener) {
    mSelectionListeners.add(selectionlistener);
}

}