Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Can someone show me a code efficient way to have an object property in spring mvc change based on parameters sent to it from a hyperlink?

I am modifying the spring petclinic sample application so that an "owner" detail page can show separate lists of each type of "pet" that the specific "owner" owns. Currently, a list of "pets" is a property of each "owner" and is accessible in jstl as owner.pets. What I want is for my jstl code to be able to call owner.cats, owner.dogs, owner.lizards, etc from jstl, and to populate several separate lists in different parts of the web page, even though all the cats, dogs, and lizards are stored in the same underlying data table.

How do I accomplish this?

Here are the relevant methods of JpaOwnerRepositoryImpl.java:

@SuppressWarnings("unchecked")
public Collection<Owner> findByLastName(String lastName) {
    // using 'join fetch' because a single query should load both owners and pets
    // using 'left join fetch' because it might happen that an owner does not have pets yet
    Query query = this.em.createQuery("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.lastName LIKE :lastName");
    query.setParameter("lastName", lastName + "%");
    return query.getResultList();
}

@Override
public Owner findById(int id) {
    // using 'join fetch' because a single query should load both owners and pets
    // using 'left join fetch' because it might happen that an owner does not have pets yet
    Query query = this.em.createQuery("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id");
    query.setParameter("id", id);
    return (Owner) query.getSingleResult();
}

Here are relevant aspects of Owner.java:

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

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

Here is the part of OwnerController.java that manages the url pattern "/owners" from which I want my jstl to be able to separately list cats, dogs, lizards, etc in separate parts of the page (not in one grouped list, but in several separate lists.):

@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);
    model.put("sel_owner",this.clinicService.findOwnerById(ownrId));
    return "owners/ownersList";
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
147 views
Welcome To Ask or Share your Answers For Others

1 Answer

Since you asked for a non-verbose solution, you could just do this kind of semi-dirty fix.

Owner.java

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

[...]

// Call this from OwnerController before returning data to page.
public void parsePets() {
  for (Pet pet : getPetsInternal()) {
    if ("cat".equals(pet.getType().getName())) {
      cats.add(pet);
    }
  }
}

public getCats() {
  return cats;
}

ownerDetail.jsp

[...]
<h3>Cats</h3>
<c:forEach var="cat" items="${owner.cats}">
    <p>Name: <c:out value="${cat.name}" /></p>
</c:forEach>

<h3>All pets</h3>
[...]

OwnerController.java

/**
 * Custom handler for displaying an owner.
 *
 * @param ownerId the ID of the owner to display
 * @return a ModelMap with the model attributes for the view
 */
@RequestMapping("/owners/{ownerId}")
public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
    ModelAndView mav = new ModelAndView("owners/ownerDetails");
    Owner owner = this.clinicService.findOwnerById(ownerId);
    owner.parsePets();
    mav.addObject(owner);
    return mav;
}

Screenshot of the change


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...