在模型中显示筛选列表以进行查看

时间:2013-11-30 18:41:44

标签: java spring hibernate jsp jpa-2.0

我的spring-mvc-hibernate应用程序有三个Pet对象列表(petscatsdogs),这些对象填充在模型中({{1}需要通过控制器(OwnerController.java)发送到视图(映射到/ owner url模式的jsp)。所有三个列表都应该从底层数据库中的相同Owner表填充,pets列表包括pets表中的所有列表和pets列表仅包括cats表中猫的条目,pets列表仅包括来自dogs表的狗的条目。 问题是所有三个列表都填充了所有宠物,无论其类型如何。 我已通过System.out.println()命令确认 列表填充的问题发生在模型级别 。如何让pets列表仅包含猫,cats列表仅包含狗?

以下是模型的相关代码,Owner.java:

dogs

以下是来自控制器的相关代码,OwnerController.java:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
private Set<Pet> pets;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "owner", fetch=FetchType.EAGER)
private Set<Pet> cats;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "owner", fetch=FetchType.EAGER)
private Set<Pet> dogs;

protected void setPetsInternal(Set<Pet> pets) {this.pets = pets;}

// Call this from OwnerController before returning data to page.
public void parsePets() {
    for (Pet pet : getPetsInternal()) {
        if (pet.getType().getName().equals("cat")) {
            cats.add(pet);
            System.out.println(pet.getType().getName());
            System.out.println("cats.size() is: "+cats.size());
            System.out.println("added a cat to cats");
        } 
        else if (pet.getType().getName().equals("dog")) {
            dogs.add(pet);
            System.out.println(pet.getType().getName());
            System.out.println("dogs.size() is: "+dogs.size());
            System.out.println("added a dog to dogs");
        }
        // add as many as you want
        System.out.println("-----------------------------------------------------------");
      }
    }

public Set<Pet> getCats() {
    System.out.println("about to return cats");
    for (Pet cat : cats) {System.out.println("counting a "+cat.getType()+" in cats.");}
    System.out.println("cats.size() is: "+cats.size());
    return cats;
}

public Set<Pet> getDogs() {
    System.out.println("about to return dogs");
    for (Pet dog : cats) {System.out.println("counting a "+dog.getType()+" in dogs.");}
    System.out.println("dogs.size() is: "+dogs.size());
    return dogs;
}

protected Set<Pet> getPetsInternal() {
    if (this.pets == null) {this.pets = new HashSet<Pet>();}
    return this.pets;
}

public List<Pet> getPets() {
    List<Pet> sortedPets = new ArrayList<Pet>(getPetsInternal());
    PropertyComparator.sort(sortedPets, new MutableSortDefinition("name", true, true));
    return Collections.unmodifiableList(sortedPets);
}  

这里是来自jsp视图的相关代码,请注意三个蒲公英数据表中的每一个都是相同的,除了每个数据表都用于单独的列表,宠物,猫或狗:

@RequestMapping(value = "/owners", method = RequestMethod.GET)
public String processFindForm(@RequestParam("ownerID") String ownerId, Owner owner, BindingResult result, Map<String, Object> model) {
    Collection<Owner> results = this.clinicService.findOwnerByLastName("");
    model.put("selections", results);
    int ownrId = Integer.parseInt(ownerId);
    Owner sel_owner = this.clinicService.findOwnerById(ownrId);
    sel_owner.parsePets();
    model.put("sel_owner",sel_owner);
    return "owners/ownersList";
}

编辑:

当我在猫和狗之前注释掉@OneToMany注释时,会抛出以下错误:

<datatables:table id="pets" data="${sel_owner.pets}" cdn="true" row="pet" theme="bootstrap2" 
                  cssClass="table table-striped" paginate="false" info="false"  filter="false"
                  cssStyle="width: 350px;" align="left" >
    <datatables:column title="Name" cssStyle="width: 200px;" display="html">
        <c:out value="${pet.name}"/>
    </datatables:column>
    <datatables:column title="BirthDate" cssStyle="width: 300px;" display="html">
        <joda:format value="${pet.birthDate}" pattern="yyyy-MM-dd"/>
    </datatables:column>
    <datatables:column title="Type" cssStyle="width: 200px;" display="html">
        <c:out value="${pet.type.name}"/>
    </datatables:column>
</datatables:table>

<datatables:table id="cats" data="${sel_owner.cats}" cdn="true" row="cat" theme="bootstrap2" 
            cssClass="table table-striped" paginate="false" info="false"  filter="false"
            cssStyle="width: 350px;" align="left" >
    <datatables:column title="Name" cssStyle="width: 200px;" display="html">
        <c:out value="${cat.name}"/>
    </datatables:column>
    <datatables:column title="BirthDate" cssStyle="width: 300px;" display="html">
        <joda:format value="${cat.birthDate}" pattern="yyyy-MM-dd"/>
    </datatables:column>
    <datatables:column title="Type" cssStyle="width: 200px;" display="html">
        <c:out value="${cat.type.name}"/>
    </datatables:column>
</datatables:table>

<datatables:table id="dogs" data="${sel_owner.dogs}" cdn="true" row="dog" theme="bootstrap2" 
              cssClass="table table-striped" paginate="false" info="false"  filter="false"
              cssStyle="width: 350px;" align="left" >
    <datatables:column title="Name" cssStyle="width: 200px;" display="html">
           <c:out value="${dog.name}"/>
    </datatables:column>
    <datatables:column title="BirthDate" cssStyle="width: 300px;" display="html">      
        <joda:format value="${dog.birthDate}" pattern="yyyy-MM-dd"/>
    </datatables:column>
    <datatables:column title="Type" cssStyle="width: 200px;" display="html">
        <c:out value="${dog.type.name}"/>
    </datatables:column>
</datatables:table>

请注意,Cat和Dog未定义为类,因为此时它们不存储与宠物不同的信息或方法,我想简化代码。我需要制作Cat课程和Dog课程吗?或者我可以解决这个问题,而无需单独的类?


第二次编辑:

我添加了@Transactional并在猫和狗的声明之前注释了// @ OneToMany(...),但在宠物声明之前留下了@OneToMany(...)注释。我还添加了

Caused by: org.hibernate.MappingException:  
Could not determine type for:  
java.util.Set, at table: owners, for columns: [org.hibernate.mapping.Column(cats)]

宣布猫和狗。但是,现在应用程序无法在我执行Run As时初始化...在eclipse中运行服务器:

= new HashSet<Pet>();  

business-config.xml的代码can be read at this link.任何人都可以告诉我如何解决这个问题吗?

我可以通过注释掉更改消除错误消息并让应用程序运行,但是当我需要猫和狗时,我留下三个列表(宠物,猫,狗)相同的问题每个都是不同的宠物子集。下面是代码,它消除了错误消息,但创建了三个相同的列表,这些列表不应该相同:

org.springframework.beans.factory.BeanCreationException:  
Error creating bean with name  
'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0'  
defined in class path resource [spring/business-config.xml]: Initialization of bean failed;  
nested exception is org.springframework.beans.factory.BeanCreationException:  
Error creating bean with name 'entityManagerFactory' defined in class path resource  
[spring/business-config.xml]: Invocation of init method failed;  
nested exception is javax.persistence.PersistenceException:  
[PersistenceUnit: petclinic] Unable to build EntityManagerFactory

2 个答案:

答案 0 :(得分:0)

您需要删除猫狗的hibernate映射!仅通过hibernate将(内部)pets列表映射到数据库。然后过滤猫狗(就像你已经做过的那样)。

我想添加宠物,然后确保将它们添加到(内部)pets列表中。

@OneToMany(cascade = CascadeType.ALL, mappedBy = "owner",  fetch=FetchType.EAGER)
private Set<Pet> pets;

/**
 * Selection of cats from pets, it is a COPY!
 * Lazy populated cache, set it to NULL for invalidation.
 * The set itself is unmodifiable!
 */
@Transient
private Set<Pet> catsCache;

/** the same for dogs: @Transient private Set<Pet> dogsCache; */

public Set<Pet> getPets() {
    return Collections.<Pet>unmodifiableCollection(this.pet);
}

public Set<Pet> getCats() {
    if (this.catsCache == null) {
        Set<Pet> catsSelection = new HashSet();
        for (Pet pet : this.pets) {
           //assume pet.type is an emum called PetType wiht an enumaration cat, if this does
           //not exist, then use: if (pet.getType().getName().equals("cat"))
           if (pet.getType() == PetType.cat)
               catsSelection.add(pet);
        }
        this.catsCache = Collections.<Pet>unmodifiableCollection(catsSelection);
    }
    return this.catsCache;
}

public void addPet(Pet catOrDog) {
    this.pets.add(catOrDog);
    this.catsCache = null;
}

答案 1 :(得分:0)

如果你想坚持你的方法,请dogscats瞬态,以便JPA不会尝试映射字段或用实体填充它们:

@Transient
private Set<Pet> cats = new HashSet<Pet>();

@Transient
private Set<Pet> dogs = new HashSet<Pet>();

如果您想要实现DogCat类来建立和继承关系,您可以按照我的tutorial进行操作。