1.1.14.4.2.7. fejezet, Hibernate tábla kapcsolatok
A Hibernate-tel a tábla kapcsolatok annotációval könnyen kezelhetők.
Request.java
package com.integrity.domain; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.persistence.Transient; import javax.validation.constraints.NotNull; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import org.hibernate.validator.constraints.Email; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotEmpty; import com.integrity.validator.FieldMatch; @Entity @Table(name="request") @XmlRootElement @FieldMatch.List({ @FieldMatch(first = "discount", second = "discountReason", message = "{com.integrity.validation.discountReason.isEmpty.message}"), @FieldMatch(first = "operationType.id", second = "serviceId", message = "{com.integrity.validation.serviceid.isEmpty.message}") }) public class Request implements Serializable { private static final long serialVersionUID = -3828086455549895099L; private Long id; private String name; private String phone; private String email; private String organization; private String subject; private OperationType operationType; @Transient private String operatoinTypeLabel; private String serviceId; private String homepage; private ApplicantType applicantType; @Transient private String applicantTypeLabel; private String startTime; @Transient private String startTimeLabel; private Boolean discount; private String discountReason; private String comment; public static String CONTRACTION_YES = "I"; public static String CONTRACTION_NO = "N"; public static String CONTRACTION_TRUE = "true"; public static String CONTRACTION_FALSE = "false"; public static String UNIFIED_YES_HU = "Igen"; public static String UNIFIED_NO_HU = "Nem"; public static String SERVICE_GROW = "B"; public static String SERVICE_SWITCH = "L"; public static String SERVICE_NEW = "U"; /** * @return the id */ @Id @GeneratedValue @Column(name="ID") @XmlAttribute public Long getId() { return id; } /** * @param id the id to set */ public void setId(Long id) { this.id = id; } /** * @return the nev */ @Column(name="name") @Length(max = 64) @XmlElement @NotNull @NotEmpty public String getName() { return name; } /** * @param name the nev to set */ public void setName(String name) { this.name = name; } /** * @return the telefonszam */ @Column(name="phone") @XmlElement @NotNull @NotEmpty public String getPhone() { return phone; } /** * @param phone the telefonszam to set */ public void setPhone(String phone) { this.phone = phone; } /** * @return the email */ @Email @Column(name="email") @XmlElement @NotNull @NotEmpty public String getEmail() { return email; } /** * @param email the email to set */ public void setEmail(String email) { this.email = email; } /** * @return the szervezetnev */ @Column(name="organization") @XmlElement @NotNull @NotEmpty public String getOrganization() { return organization; } /** * @param szervezetnev the szervezetnev to set */ public void setOrganization(String organization) { this.organization = organization; } /** * @return the targy */ @Column(name="subject") @XmlElement public String getSubject() { return subject; } /** * @param subject the targy to set */ public void setSubject(String subject) { this.subject = subject; } /** * @return the muveletjelleg */ //@Column(name="operation_type") @ManyToOne @JoinColumn(name = "operation_type", referencedColumnName = "id") @XmlElement @NotNull @NotEmpty public OperationType getOperationType() { return operationType; } /** * @param operationType the muveletjelleg to set */ public void setOperationType(OperationType operationType) { this.operationType = operationType; } /** * @return the serviceID */ @Column(name="service_id") @XmlElement public String getServiceId() { return serviceId; } /** * @param serviceId the serviceId to set */ public void setServiceId(String service_id) { this.serviceId = service_id; } /** * @return the honlap */ @Column(name="homepage") @XmlElement public String getHomepage() { return homepage; } /** * @param homepage the honlap to set */ public void setHomepage(String homepage) { this.homepage = homepage; } /** * @return the kerelmezojelleg */ @ManyToOne @JoinColumn(name = "applicant_type", referencedColumnName = "id") @XmlElement @NotNull @NotEmpty public ApplicantType getApplicantType() { return applicantType; } /** * @param applicantType the kerelmezojelleg to set */ public void setApplicantType(ApplicantType applicantType) { this.applicantType = applicantType; } /** * @return the szolgaltatasido */ @Column(name="start_time") @XmlElement @NotEmpty @NotNull public String getStartTime() { return startTime; } /** * @param startTime the szolgaltatasido to set */ public void setStartTime(String startTime) { this.startTime = startTime; } /** * @return the kedvezmeny */ @Column(name="discount") @XmlElement public Boolean getDiscount() { return discount; } public void setDiscount(Boolean discount) { this.discount = discount; } /** * @return the kedvezmenyoka */ @Column(name="discount_reason") @XmlElement public String getDiscountReason() { return discountReason; } /** * @param discountReason the kedvezmenyoka to set */ public void setDiscountReason(String discountReason) { this.discountReason = discountReason; } /** * @return the megjegyzes */ @Column(name="comment") @XmlElement public String getComment() { return comment; } /** * @param comment the megjegyzes to set */ public void setComment(String comment) { this.comment = comment; } @XmlElement @Transient public String getOperationTypeLabel() { return operatoinTypeLabel; } public void setOperationTypeLabel(String muveletjellegLabel) { this.operatoinTypeLabel = muveletjellegLabel; } @XmlElement @Transient public String getApplicantTypeLabel() { return applicantTypeLabel; } public void setApplicantTypeLabel(String applicantTypeLabel) { this.applicantTypeLabel = applicantTypeLabel; } @XmlElement @Transient public String getStartTimeLabel() { return startTimeLabel; } public void setStartTimeLabel(String startTimeLabel) { this.startTimeLabel = startTimeLabel; } @XmlElement @Transient public String getDiscountLabel() { return ((discount!=null) && discount ? UNIFIED_YES_HU : UNIFIED_NO_HU); } }
A fenti kódban három mezőt érintett az annotációs kapcsolat: ApplicantType, StartTime, és OperationType. Az egyedi annotációs validáció (@FieldMatch) az utóbbi mezőnek megváltozott. Az operationType.id az objektum egyedi azonosítója. Ezt megtehetjük, mert a BeanUtils.getProperty() metódusa kezeli az objektumok mezőire való hivatkozást is.
public boolean isValid(final Object value, final ConstraintValidatorContext context) { try { final Object firstObj = BeanUtils.getProperty(value, firstFieldName); final Object secondObj = BeanUtils.getProperty(value, secondFieldName); if (firstFieldName.equalsIgnoreCase("operationtype.id")){ String operationTypeId = (String)firstObj; return operationTypeId.equals(Request.SERVICE_NEW) || (!secondObj.toString().isEmpty() && (operationTypeId.equals(Request.SERVICE_SWITCH) || operationTypeId.equals(Request.SERVICE_GROW))); } else if (firstFieldName.equalsIgnoreCase("discount")) { return firstObj.toString().equalsIgnoreCase("false") || (!secondObj.toString().isEmpty() && firstObj.toString().equalsIgnoreCase("true")); } } catch (final Exception ignore) { // ignore } return true; }
A Trasient mezők úgy válnak feleslegessé, hogy Converter-t alkalmazunk a legördülő ablakoknál:
<p:selectOneMenu effect="fade" id="applicantType" label="#{text['request.applicant_type.label']}" value="#{serviceRequest.applicantType}"> <f:selectItem itemLabel="Válasszon egyet" itemValue=""/> <f:selectItems value="#{myApplicantTypeDAO.getApplicantTypeList()}" var="applicantTypeVar" itemValue="#{applicantTypeVar.id}" itemLabel="#{applicantTypeVar.name}"/> <f:converter converterId="com.integrity.converter.ApplicantTypeConverter"/> </p:selectOneMenu>
Az ApplicantTypeConverter így néz ki:
package com.integrity.converter; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.convert.Converter; import javax.faces.convert.ConverterException; import javax.servlet.http.HttpServletRequest; import com.integrity.dao.ApplicantTypeDAO; import com.integrity.domain.ApplicantType; public class ApplicantTypeConverter implements Converter { public final static String CONVERTER_ID = "com.integrity.converter.ApplicantTypeConverter"; private ApplicantTypeDAO applicantTypeDAO; public void setApplicantTypeDAO(ApplicantTypeDAO applicantTypeDAO) { this.applicantTypeDAO = applicantTypeDAO; } @Override public Object getAsObject(FacesContext context, UIComponent component, String value) { if (value == null) { return null; } try { if (applicantTypeDAO == null) { HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest(); applicantTypeDAO = (ApplicantTypeDAO)request.getSession().getAttribute("myApplicantTypeDAO"); } if (applicantTypeDAO != null) { ApplicantType applicantType = applicantTypeDAO.getApplicantType(value); return applicantType; } else { ApplicantType applicantType = new ApplicantType(); applicantType.setId(value); applicantType.setName(value); return applicantType; } } catch (NumberFormatException ex) { throw new ConverterException("Number converter exception (" + value + ").", ex); } catch (IllegalArgumentException ex) { throw new ConverterException("Illegal argument exception (" + value + ").", ex); } catch (Exception ex) { throw new ConverterException("Other conversion exception (" + value + ").", ex); } } @Override public String getAsString(FacesContext context, UIComponent component, Object value) { if (value instanceof ApplicantType) { return ((ApplicantType) value).getId(); } else { return value.toString(); } } }
Itt a példa egy session-ből előkeresett Bean-re. A myApplicantTypeDAO session láthatósági körrel (scope) rendelkezik. Ezt a Spring servlet-context.xml-ben definiáltuk.
<bean id="myApplicantTypeDAO" class="com.integrity.dao.ApplicantTypeDAOImpl" scope="session"> <property name="sessionFactory" ref="mySessionFactory"/> </bean>
Ezzel érhető el, hogy a Spring-ben nem definiált Converter lássa a DAO Bean-t. Még egy változtatást eszközölnünk kell az ApplicantType osztályban, hogy azonosítani tudjuk programunkban az ApplicantType osztályból gyártott objektumokat. Ez lényeges az objektum szöveges megjelenítésben és az egyedi azonosításban.
package com.integrity.domain; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="applicant_type") public class ApplicantType implements Serializable { /** * */ private static final long serialVersionUID = -1106868578703357156L; private String id; private String name; @Id public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode(){ int hash = 0; hash += (id != null ? id.hashCode() : 0); return hash; } @Override public boolean equals(Object object){ if (!(object instanceof ApplicantType)){ return false; } return ((ApplicantType)object).id.equalsIgnoreCase(id); } /* @Override public String toString() { return "com.integrity.domain.ApplicantType[id=" + id + "]"; } //*/ }
A hashCode és az equals metódusokat kell felülírnunk. A toString akkor lehet szükséges, ha több mezős az egyedi azonosítás.
Példák a kapcsolat jellegére:
- A hozzászóláshoz be kell jelentkezni