JSF : 将Collection集合内容放入selectOneMenu组件
比如我们有如下的Plate类package com.bbpop.entity;
import javax.persistence.*;
/**
*
* @author vlinux
*/
@Entity
@Table(name = "PLATE")
public class Plate implements java.io.Serializable {
public Plate() {
this.locked = false;
this.hidden = false;
}
public Plate(String title, String comment) {
this();
this.title = title;
this.comment = comment;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private Integer id;
@Column(name = "TITLE", columnDefinition = "VARCHAR(100)", nullable = false)
private String title;
@Column(name = "COMMENT", columnDefinition = "VARCHAR(100)", nullable = false)
private String comment;
@Column(name = "LOCKED", nullable = false)
private boolean locked;
@Column(name = "HIDDEN", nullable = false)
private boolean hidden;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "RULE", joinColumns = {@JoinColumn(name = "PLATE_ID")}, inverseJoinColumns = {@JoinColumn(name = "ACCOUNT_ID")})
private java.util.Collection<Account> masters;
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public java.lang.String getTitle() {
return title;
}
public void setTitle(java.lang.String title) {
this.title = title;
}
public java.lang.String getComment() {
return comment;
}
public void setComment(java.lang.String comment) {
this.comment = comment;
}
public boolean getLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public boolean getHidden() {
return hidden;
}
public void setHidden(boolean hidden) {
this.hidden = hidden;
}
public java.util.Collection<Account> getMasters() {
return masters;
}
public void setMasters(java.util.Collection<Account> masters) {
this.masters = masters;
}
}
import javax.persistence.*;
/**
*
* @author vlinux
*/
@Entity
@Table(name = "PLATE")
public class Plate implements java.io.Serializable {
public Plate() {
this.locked = false;
this.hidden = false;
}
public Plate(String title, String comment) {
this();
this.title = title;
this.comment = comment;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private Integer id;
@Column(name = "TITLE", columnDefinition = "VARCHAR(100)", nullable = false)
private String title;
@Column(name = "COMMENT", columnDefinition = "VARCHAR(100)", nullable = false)
private String comment;
@Column(name = "LOCKED", nullable = false)
private boolean locked;
@Column(name = "HIDDEN", nullable = false)
private boolean hidden;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "RULE", joinColumns = {@JoinColumn(name = "PLATE_ID")}, inverseJoinColumns = {@JoinColumn(name = "ACCOUNT_ID")})
private java.util.Collection<Account> masters;
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public java.lang.String getTitle() {
return title;
}
public void setTitle(java.lang.String title) {
this.title = title;
}
public java.lang.String getComment() {
return comment;
}
public void setComment(java.lang.String comment) {
this.comment = comment;
}
public boolean getLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public boolean getHidden() {
return hidden;
}
public void setHidden(boolean hidden) {
this.hidden = hidden;
}
public java.util.Collection<Account> getMasters() {
return masters;
}
public void setMasters(java.util.Collection<Account> masters) {
this.masters = masters;
}
}
然后我们企图通过访问plate.getMasters()把版主的Username放入一个selectOneMenu,很遗憾,这是不可能的,因为selectOneMenu接收的是一个
Collection<SelectItem>组件。
怎么解决?我们可以在PlateBacking中创建一个内部类PlateBean
package com.bbpop.jsf.backing;
import com.bbpop.entity.Account;
import com.bbpop.entity.Plate;
import com.bbpop.service.PlateService;
import java.util.Collection;
import javax.faces.component.html.HtmlDataTable;
import javax.faces.model.SelectItem;
/**
*
* @author vlinux
*/
public class PlateBacking {
private HtmlDataTable plateDataTable;
public class PlateBean extends Plate {
private Collection<SelectItem> masters;
public Collection<SelectItem> getMasterUsernames() {return masters;}
public PlateBean( Plate plate ) {
this.setComment(plate.getComment());
this.setHidden(plate.getHidden());
this.setId(plate.getId());
this.setLocked(plate.getLocked());
this.setTitle(plate.getTitle());
masters = new java.util.ArrayList<SelectItem>();
for( Account master : plate.getMasters() ) {
masters.add( new SelectItem(master.getUsername(),master.getUsername()) );
}
}
}
public Collection<PlateBean> getPlates() {
Collection<PlateBean> plates = new java.util.ArrayList<PlateBean>();
for( Plate plate : plateService.findByUnHidden() ) {
plates.add( new PlateBean(plate) );
}
return plates;
}
private PlateService plateService;
public void setPlateService( PlateService plateService ) {
this.plateService = plateService;
}
}
import com.bbpop.entity.Account;
import com.bbpop.entity.Plate;
import com.bbpop.service.PlateService;
import java.util.Collection;
import javax.faces.component.html.HtmlDataTable;
import javax.faces.model.SelectItem;
/**
*
* @author vlinux
*/
public class PlateBacking {
private HtmlDataTable plateDataTable;
public class PlateBean extends Plate {
private Collection<SelectItem> masters;
public Collection<SelectItem> getMasterUsernames() {return masters;}
public PlateBean( Plate plate ) {
this.setComment(plate.getComment());
this.setHidden(plate.getHidden());
this.setId(plate.getId());
this.setLocked(plate.getLocked());
this.setTitle(plate.getTitle());
masters = new java.util.ArrayList<SelectItem>();
for( Account master : plate.getMasters() ) {
masters.add( new SelectItem(master.getUsername(),master.getUsername()) );
}
}
}
public Collection<PlateBean> getPlates() {
Collection<PlateBean> plates = new java.util.ArrayList<PlateBean>();
for( Plate plate : plateService.findByUnHidden() ) {
plates.add( new PlateBean(plate) );
}
return plates;
}
private PlateService plateService;
public void setPlateService( PlateService plateService ) {
this.plateService = plateService;
}
}
这样我们就可以很轻松的通过JSF的核心标签<f:selectItems/>将原本属于Collection<Account>的东西转换到其中
总结:灵活运用内部类能解决很多问题。如果这个内部类能抽象出来则抽象出来作为JSF的一个独立的托管BEAN更好。