我正在开发卡路里计算器。我有实体Dish
(由食材或其他菜肴组成的食物)和Ingredient
(原子食用,例如“土豆”的“水”)。两者都扩展了实现接口AbstractEdible
的类Edible
。
Dish
包含recipe
类型的字段Map<Edible, Double>
,其中Double
表示每个“菜元素”(成分或其他菜肴)的重量。
我正在尝试使用JPA和Derby来保留所有这些内容。我希望有一个包含以下字段的连接表:
DOUBLE
表示“菜单元素”重量的值这就是我现实中所拥有的:
而不是VARCHAR
关键字“碟元素”实体我有一个BLOB
而我无法找出原因。因此,我在更新现有的Dish时遇到问题(获得ERROR 42818: Comparisons between 'BLOB' and 'BLOB' are not supported
)。我真的很乐意帮助你!
菜
package com.singularityfx.kcalibri2.model.edibles;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.MapKeyJoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Transient;
import javax.persistence.JoinColumn;
@Entity
public class Dish extends AbstractEdible implements EdiblesCollection {
@Transient
private static final long serialVersionUID = -5646610412222252829L;
@ElementCollection
@CollectionTable(name="dish_recipe")
@Column(name="weight")
@MapKeyJoinColumn(name="ingredient_or_dish", referencedColumnName="name")
private Map<Edible, Double> recipe = new HashMap<Edible, Double>();
@Transient
private KCalculator kCalculator = new KCalculator();
public Dish() {}
public Dish(String name, DishCategory category) {
this.name = name;
this.category = category;
}
@Override
public double getKCalNonDessert() {
kCalculator.init(recipe);
return kCalculator.getkCalNonDessertPer100g();
}
@Override
public double getKCalDessert() {
kCalculator.init(recipe);
return kCalculator.getkCalDessertPer100g();
}
@Override
public double getKCal() {
kCalculator.init(recipe);
return kCalculator.getkCalPer100g();
}
@Override
public double getKCalDessertTotal() {
kCalculator.init(recipe);
return kCalculator.getTotalKCalDessert();
}
@Override
public double getKCalNonDessertTotal() {
kCalculator.init(recipe);
return kCalculator.getTotalKCalNonDessert();
}
@Override
public double getKCalTotal() {
kCalculator.init(recipe);
return kCalculator.getTotalKCal();
}
public Double addIngredient(Edible edible, Double weight) {
return recipe.put(edible, weight);
}
public Double removeIngredient(Edible edible) {
return recipe.remove(edible);
}
@Override
public Map<Edible, Double> getContent() {
return recipe;
}
@Override
public void setContent(Map<Edible, Double> content) {
this.recipe = content;
}
@Override
public void clearContent() {
this.recipe.clear();
}
public double getWeight(Edible edible) {
return recipe.get(edible);
}
public Collection<Edible> getEdibles() {
return recipe.keySet();
}
}
成分
package com.singularityfx.kcalibri2.model.edibles;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.NamedQuery;
import javax.persistence.Transient;
@Entity
public class Ingredient extends AbstractEdible {
@Transient
private static final long serialVersionUID = -7669934586986624995L;
private double kCal;
private boolean isDessert;
public Ingredient() {}
public Ingredient(String name, IngredientCategory category,
double kCal, boolean isDessert) {
this.name = name;
this.kCal = kCal;
this.category = category;
this.isDessert = isDessert;
}
@Override
public double getKCalNonDessert() {
return isDessert ? 0 : kCal;
}
@Override
public double getKCalDessert() {
return isDessert ? kCal : 0;
}
}
AbstractEdible
package com.singularityfx.kcalibri2.model.edibles;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToOne;
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class AbstractEdible implements Edible, Serializable {
private static final long serialVersionUID = 8684184950268663225L;
@Id
protected String name;
@OneToOne()
@JoinColumn(name="NAME_OF_CATEGORY")
protected EdibleCategory category;
@Override
public String getName() {
return name;
}
@Override
public EdibleCategory getCategory() {
return category;
}
public void setName(String name) {
this.name = name;
}
public void setCategory(EdibleCategory category) {
this.category = category;
}
@Override
public String toString() {
return name + " [" + category + "]";
}
@Override
public int compareTo(Edible c) {
return name.compareTo(c.getName());
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((category == null) ? 0 : category.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AbstractEdible other = (AbstractEdible) obj;
if (category == null) {
if (other.category != null)
return false;
} else if (!category.equals(other.category))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
食用
package com.singularityfx.kcalibri2.model.edibles;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
public interface Edible extends Comparable<Edible> {
public double getKCalNonDessert();
public double getKCalDessert();
public String getName();
public EdibleCategory getCategory();
}
答案 0 :(得分:1)
您的Edible界面扩展了Comparable。因此,您应该在Interface或Implementing类中覆盖equals
和hashCode
。联接需要比较无法比较的对象,除非您覆盖equals
和hashCode
。
答案 1 :(得分:0)
我的错误在这里:
private Map<Edible, Double> recipe
Edible
(由我的实体实现的接口)本身不是实体,因此持久性提供程序不会将地图密钥识别为实体。
当我引用抽象类(使用@Entity
注释)而不是接口时,一切都按预期工作:
private Map<AbstractEdible, Double> recipe