Reputation: 4058
I have an issue unmarshalling a xml stream to entities. My foreign keys never get set to an object with the proper primary key, they just get set to an emtpy object.
The class with the foreign keys is called ProductBase. It has a reference to BrandData(field pkId) and Categories(field pkId). When I unmarshal and persist I can process BrandData and Categories just fine. I run into problems with ProductBase.
Here is ProductBase:
@XmlAccessorType(XmlAccessType.PROPERTY)
@Entity
@Table(name = "product_base")
@NamedQueries({
@NamedQuery(name = "ProductBase.findAll", query = "SELECT p FROM ProductBase p"),
@NamedQuery(name = "ProductBase.findByPkId", query = "SELECT p FROM ProductBase p WHERE p.pkId = :pkId"),
@NamedQuery(name = "ProductBase.findByColorsAvail", query = "SELECT p FROM ProductBase p WHERE p.colorsAvail = :colorsAvail"),
@NamedQuery(name = "ProductBase.findBySeriesName", query = "SELECT p FROM ProductBase p WHERE p.seriesName = :seriesName"),
@NamedQuery(name = "ProductBase.findByStatusCodes", query = "SELECT p FROM ProductBase p WHERE p.statusCodes = :statusCodes"),
@NamedQuery(name = "ProductBase.findByTs", query = "SELECT p FROM ProductBase p WHERE p.ts = :ts")})
public class ProductBase implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "pk_id")
private Integer pkId;
@Column(name = "colors_avail")
private String colorsAvail;
@Column(name = "series_name")
private String seriesName;
@Column(name = "status_codes")
private String statusCodes;
@Basic(optional = false)
@Column(name = "ts")
@Temporal(TemporalType.TIMESTAMP)
private Date ts;
@OneToMany(mappedBy = "productBase", fetch = FetchType.LAZY)
private Collection<ProductSorts> productSortsCollection;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "productBase", fetch = FetchType.LAZY)
private MapTarget mapTarget;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "productBase", fetch = FetchType.LAZY)
private KeyFeatures keyFeatures;
@JoinColumn(name = "pk_category", referencedColumnName = "pk_id")
@ManyToOne( optional = false, fetch = FetchType.LAZY)
private Categories categories;
@JoinColumn(name = "pk_brand", referencedColumnName = "pk_id")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private BrandData brandData;
@OneToMany(mappedBy = "productBase", fetch = FetchType.LAZY)
private Collection<PromotionsByModel> promotionsByModelCollection;
@OneToMany(mappedBy = "productBase", fetch = FetchType.LAZY)
private Collection<ProductEnhancedFeatures> productEnhancementFeaturesCollection;
@OneToMany(mappedBy = "productBase", fetch = FetchType.LAZY)
private Collection<SkuBasic> skuBasicCollection;
@OneToMany(mappedBy = "productBase", fetch = FetchType.LAZY)
private Collection<ProductMeasurements> productMeasurementsCollection;
public ProductBase() {
}
public ProductBase(Integer pkId) {
this.pkId = pkId;
}
public ProductBase(Integer pkId, Date ts) {
this.pkId = pkId;
this.ts = ts;
}
@XmlElement(name = "pkID")
public Integer getPkId() {
return pkId;
}
public void setPkId(Integer pkId) {
this.pkId = pkId;
}
@XmlElement(name = "ColorsAvail")
public String getColorsAvail() {
return colorsAvail;
}
public void setColorsAvail(String colorsAvail) {
this.colorsAvail = colorsAvail;
}
@XmlElement(name = "SeriesName")
public String getSeriesName() {
return seriesName;
}
public void setSeriesName(String seriesName) {
this.seriesName = seriesName;
}
@XmlElement(name = "StatusCodes")
public String getStatusCodes() {
return statusCodes;
}
public void setStatusCodes(String statusCodes) {
this.statusCodes = statusCodes;
}
@XmlElement(name = "ts", required = true)
@XmlSchemaType(name = "dateTime")
public Date getTs() {
return ts;
}
public void setTs(Date ts) {
this.ts = ts;
}
@XmlTransient
public Collection<ProductSorts> getProductSortsCollection() {
return productSortsCollection;
}
public void setProductSortsCollection(Collection<ProductSorts> productSortsCollection) {
this.productSortsCollection = productSortsCollection;
}
@XmlTransient
public MapTarget getMapTarget() {
return mapTarget;
}
public void setMapTarget(MapTarget mapTarget) {
this.mapTarget = mapTarget;
}
@XmlTransient
public KeyFeatures getKeyFeatures() {
return keyFeatures;
}
public void setKeyFeatures(KeyFeatures keyFeatures) {
this.keyFeatures = keyFeatures;
}
@XmlElement(name = "pkCategory")
public Categories getCategories() {
return categories;
}
public void setCategories(Categories categories) {
this.categories = categories;
}
@XmlElement(name = "pkBrand")
public BrandData getBrandData() {
return brandData;
}
public void setBrandData(BrandData brandData) {
this.brandData = brandData;
}
@XmlTransient
public Collection<PromotionsByModel> getPromotionsByModelCollection() {
return promotionsByModelCollection;
}
public void setPromotionsByModelCollection(Collection<PromotionsByModel> promotionsByModelCollection) {
this.promotionsByModelCollection = promotionsByModelCollection;
}
@XmlTransient
public Collection<ProductEnhancedFeatures> getProductEnhancementFeaturesCollection() {
return productEnhancementFeaturesCollection;
}
public void setProductEnhancementFeaturesCollection(Collection<ProductEnhancedFeatures> productEnhancementFeaturesCollection) {
this.productEnhancementFeaturesCollection = productEnhancementFeaturesCollection;
}
@XmlTransient
public Collection<SkuBasic> getSkuBasicCollection() {
return skuBasicCollection;
}
public void setSkuBasicCollection(Collection<SkuBasic> skuBasicCollection) {
this.skuBasicCollection = skuBasicCollection;
}
@XmlTransient
public Collection<ProductMeasurements> getProductMeasurementsCollection() {
return productMeasurementsCollection;
}
public void setProductMeasurementsCollection(Collection<ProductMeasurements> productMeasurementsCollection) {
this.productMeasurementsCollection = productMeasurementsCollection;
}
@Override
public int hashCode() {
int hash = 0;
hash += (pkId != null ? pkId.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof ProductBase)) {
return false;
}
ProductBase other = (ProductBase) object;
if ((this.pkId == null && other.pkId != null) || (this.pkId != null && !this.pkId.equals(other.pkId))) {
return false;
}
return true;
}
@Override
public String toString() {
return "entities.cmic.ajrs.com.ProductBase[pkId=" + pkId + "]";
}
Unmarshalling the following:
<ProductBase>
<pkID>88294</pkID>
<pkBrand>18</pkBrand>
<pkCategory>35</pkCategory>
<ColorsAvail>W</ColorsAvail>
<StatusCodes/>
<ts>1970-01-01T05:22:35.06</ts>
</ProductBase>
I would want to end up with a ProductBase object like so:
ProductBase p1:
p1.pkId=88294
p1.brandData = (brandData object with pkId of 18)
p1.categories = (Categories object with pkId of 35)
p1.ts = (Date object with value 1970-01-01T05:22:35.06)
However I get
ProductBase p1: p1.pkId=88294 p1.brandData = (brandData object every field null) p1.categories = (Categories object every field null) p1.ts = (Date object with value 1970-01-01T05:22:35.06)
So when I go to persist the ProductBase it has issues with null values.
I was hoping this was due to improper references in the BradnData and Categories entity. I tried using the @XmlInverseReference annotations with no luck. Anyone see what the problem may be?
BrandData entity:
@XmlAccessorType(XmlAccessType.PROPERTY)
@Entity
@Table(name = "brand_data")
@NamedQueries({
@NamedQuery(name = "BrandData.findAll", query = "SELECT b FROM BrandData b"),
@NamedQuery(name = "BrandData.findByPkId", query = "SELECT b FROM BrandData b WHERE b.pkId = :pkId"),
@NamedQuery(name = "BrandData.findByCommonBrandId", query = "SELECT b FROM BrandData b WHERE b.commonBrandId = :commonBrandId"),
@NamedQuery(name = "BrandData.findByCommonBrandName", query = "SELECT b FROM BrandData b WHERE b.commonBrandName = :commonBrandName"),
@NamedQuery(name = "BrandData.findByTs", query = "SELECT b FROM BrandData b WHERE b.ts = :ts")})
public class BrandData implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "pk_id")
private Integer pkId;
@Column(name = "common_brand_id")
private String commonBrandId;
@Column(name = "common_brand_name")
private String commonBrandName;
@Basic(optional = false)
@Column(name = "ts")
@Temporal(TemporalType.TIMESTAMP)
private Date ts;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "brandData", fetch = FetchType.LAZY)
private Collection<ProductBase> productBaseCollection;
public BrandData() {
}
public BrandData(Integer pkId) {
this.pkId = pkId;
}
public BrandData(Integer pkId, Date ts) {
this.pkId = pkId;
this.ts = ts;
}
@XmlElement(name = "pkID")
public Integer getPkId() {
return pkId;
}
public void setPkId(Integer pkId) {
this.pkId = pkId;
}
@XmlElement(name = "CommonBrandID")
public String getCommonBrandId() {
return commonBrandId;
}
public void setCommonBrandId(String commonBrandId) {
this.commonBrandId = commonBrandId;
}
@XmlElement(name = "CommonBrandName")
public String getCommonBrandName() {
return commonBrandName;
}
public void setCommonBrandName(String commonBrandName) {
this.commonBrandName = commonBrandName;
}
@XmlElement(required = true)
@XmlSchemaType(name = "dateTime")
public Date getTs() {
return ts;
}
public void setTs(Date ts) {
this.ts = ts;
}
@XmlInverseReference(mappedBy ="brandData")
public Collection<ProductBase> getProductBaseCollection() {
return productBaseCollection;
}
public void setProductBaseCollection(Collection<ProductBase> productBaseCollection) {
this.productBaseCollection = productBaseCollection;
}
@Override
public int hashCode() {
int hash = 0;
hash += (pkId != null ? pkId.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof BrandData)) {
return false;
}
BrandData other = (BrandData) object;
if ((this.pkId == null && other.pkId != null) || (this.pkId != null && !this.pkId.equals(other.pkId))) {
return false;
}
return true;
}
@Override
public String toString() {
return "entities.cmic.ajrs.com.BrandData[pkId=" + pkId + "]";
}
The Categories entity:
@XmlAccessorType(XmlAccessType.PROPERTY)
@Entity
@Table(name = "categories")
@NamedQueries({
@NamedQuery(name = "Categories.findAll", query = "SELECT c FROM Categories c"),
@NamedQuery(name = "Categories.findByPkId", query = "SELECT c FROM Categories c WHERE c.pkId = :pkId"),
@NamedQuery(name = "Categories.findByPkSuperCategory", query = "SELECT c FROM Categories c WHERE c.pkSuperCategory = :pkSuperCategory"),
@NamedQuery(name = "Categories.findByCategoryId", query = "SELECT c FROM Categories c WHERE c.categoryId = :categoryId"),
@NamedQuery(name = "Categories.findByCmicDescription", query = "SELECT c FROM Categories c WHERE c.cmicDescription = :cmicDescription"),
@NamedQuery(name = "Categories.findByConsumerDescription", query = "SELECT c FROM Categories c WHERE c.consumerDescription = :consumerDescription"),
@NamedQuery(name = "Categories.findByTs", query = "SELECT c FROM Categories c WHERE c.ts = :ts")})
public class Categories implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "pk_id")
private Integer pkId;
@Column(name = "pk_super_category")
private Integer pkSuperCategory;
@Column(name = "category_id")
private String categoryId;
@Column(name = "cmic_description")
private String cmicDescription;
@Column(name = "consumer_description")
private String consumerDescription;
@Basic(optional = false)
@Column(name = "ts")
@Temporal(TemporalType.TIMESTAMP)
private Date ts;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "categories", fetch = FetchType.LAZY)
private Collection<ProductBase> productBaseCollection;
@JoinColumn(name = "pk_class", referencedColumnName = "pk_id")
@ManyToOne(fetch = FetchType.LAZY)
private Classes classes;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "categories", fetch = FetchType.LAZY)
private SortFields sortFields;
public Categories() {
}
public Categories(Integer pkId) {
this.pkId = pkId;
}
public Categories(Integer pkId, Date ts) {
this.pkId = pkId;
this.ts = ts;
}
@XmlElement(name="pkID")
public Integer getPkId() {
return pkId;
}
public void setPkId(Integer pkId) {
this.pkId = pkId;
}
public Integer getPkSuperCategory() {
return pkSuperCategory;
}
public void setPkSuperCategory(Integer pkSuperCategory) {
this.pkSuperCategory = pkSuperCategory;
}
@XmlElement(name = "Category_ID")
public String getCategoryId() {
return categoryId;
}
public void setCategoryId(String categoryId) {
this.categoryId = categoryId;
}
@XmlElement(name = "CMIC_Description")
public String getCmicDescription() {
return cmicDescription;
}
public void setCmicDescription(String cmicDescription) {
this.cmicDescription = cmicDescription;
}
@XmlElement(name = "ConsumerDescription")
public String getConsumerDescription() {
return consumerDescription;
}
public void setConsumerDescription(String consumerDescription) {
this.consumerDescription = consumerDescription;
}
@XmlElement(required = true)
@XmlSchemaType(name = "dateTime")
public Date getTs() {
return ts;
}
public void setTs(Date ts) {
this.ts = ts;
}
@XmlInverseReference(mappedBy ="categories")
public Collection<ProductBase> getProductBaseCollection() {
return productBaseCollection;
}
public void setProductBaseCollection(Collection<ProductBase> productBaseCollection) {
this.productBaseCollection = productBaseCollection;
}
public Classes getClasses() {
return classes;
}
public void setClasses(Classes classes) {
this.classes = classes;
}
@XmlTransient
public SortFields getSortFields() {
return sortFields;
}
public void setSortFields(SortFields sortFields) {
this.sortFields = sortFields;
}
@Override
public int hashCode() {
int hash = 0;
hash += (pkId != null ? pkId.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Categories)) {
return false;
}
Categories other = (Categories) object;
if ((this.pkId == null && other.pkId != null) || (this.pkId != null && !this.pkId.equals(other.pkId))) {
return false;
}
return true;
}
@Override
public String toString() {
return "entities.cmic.ajrs.com.Categories[pkId=" + pkId + "]";
}
Upvotes: 2
Views: 988
Reputation: 148977
For this use case you are going to need an XmlAdapter.
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class BrandDataAdapter extends XmlAdapter<Integer, BrandData> {
@Override
public Integer marshal(BrandData arg0) throws Exception {
return arg0.getPkId();
}
@Override
public BrandData unmarshal(Integer arg0) throws Exception {
return new BrandData(arg0);
}
}
and in ProductBase:
@JoinColumn(name = "pk_brand", referencedColumnName = "pk_id")
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@XmlJavaTypeAdapter(BrandDataApter.class)
private BrandData brandData;
For More Information
Upvotes: 2