EntityManager.find()找不到实体

时间:2016-07-08 03:20:57

标签: hibernate jpa jdbc entitymanager hibernate-entitymanager

我遇到了JPA和Hibernate的问题,EntityManager.find()甚至EntityManager.createQuery()都不会在我的数据库中返回具有相应ID的实体。前者返回null,后者抛出No entity found for query异常。我知道具有该ID的实体存在于数据库中,因为我在运行代码时盯着该条目。

我需要采取一些步骤才能找到失败的地方。首先,我在我的DayItem表中添加两个项目并将它们返回给客户端。我在客户端上更改它们的值并使用POST将它们发送回服务器。一旦收到服务器,我就创建一个新的EntityManager并尝试通过获取其类和ID并将这些值传递给EntityManager.find(Class, ID)来按ID删除实体。

这将在数据库中查找具有原始值的实体,而不是从客户端发送的已更改实体。 EntityManager.find(Class, ID)也正是问题发生的地方。找到数据库中的实体后,我会在实体上调用EntityManager.remove()将其删除。

当服务器收到实体时,我没有直接在实体上使用EntityManager.merge()的原因是因为它们的唯一密钥被交换了,这会导致约束违规,除非我从中删除它们运行EntityManager.merge()之前的数据库。

最后,在删除数据库中的实体后,我会通过调用EntityManager.merge()来更新它们的更新值。

请查看下面的代码,有关EntityManager.find()返回null的原因的任何帮助以及查询引发No entity found for query异常的原因将是一个很大的帮助。

这是DayItem表上的唯一键:

ALTER TABLE DAY_ITEM
ADD CONSTRAINT DAY_ITEM_UK
UNIQUE (EMAIL, MOD_ID, FM_ORDER, DAYS_DATE);

这是DayItem表实体:

@Entity
@Table(name = "DAY_ITEM")
public class DayItem implements GtEntity, Serializable{
    private Long id;
    private String email;
    private String name;
    private BigDecimal amount;
    private Integer modId;
    private Integer fmOrder;
    private String modName;
    private Date daysDate;
    private String daysDateString;
    private Long foodId;
    private Long mealId;
    private FoodItem foodItem;
    private MealItem mealItem;
    private ArrayList<FoodItem> foodItems;
    private ArrayList<MealItem> mealItems;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Basic
    @Column(name = "EMAIL", nullable = false, length = 50)
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Basic
    @Column(name = "NAME", nullable = true, length = 100)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Basic
    @Column(name = "AMOUNT", nullable = true)
    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }

    @Basic
    @Column(name = "MOD_ID", nullable = false)
    public Integer getModId() {
        return modId;
    }

    public void setModId(Integer modId) {
        this.modId = modId;
    }

    @Basic
    @Column(name = "FM_ORDER", nullable = false)
    public Integer getFmOrder() {
        return fmOrder;
    }

    public void setFmOrder(Integer fmOrder) {
        this.fmOrder = fmOrder;
    }

    @Basic
    @Column(name = "MOD_NAME", nullable = true, length = 50)
    public String getModName() {
        return modName;
    }

    public void setModName(String modName) {
        this.modName = modName;
    }

    @Basic
    @Column(name = "DAYS_DATE", nullable = false)
    public Date getDaysDate() {
        return daysDate;
    }

    public void setDaysDate(Date daysDate) {
        this.daysDate = daysDate;
    }

    @Transient
    public String getDaysDateString() {
        return daysDateString;
    }

    public void setDaysDateString(String daysDateString) {
        this.daysDateString = daysDateString;
    }

    @Basic
    @Column(name = "FOOD_ID", nullable = true)
    public Long getFoodId() {
        return foodId;
    }

    public void setFoodId(Long foodId) {
        this.foodId = foodId;
    }

    @Basic
    @Column(name = "MEAL_ID", nullable = true)
    public Long getMealId() {
        return mealId;
    }

    public void setMealId(Long mealId) {
        this.mealId = mealId;
    }

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "FOOD_ID", referencedColumnName = "ID",
            updatable = false, insertable = false)
    public FoodItem getFoodItem() {
        return foodItem;
    }

    public void setFoodItem(FoodItem foodItem) {
        this.foodItem = foodItem;
    }

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "MEAL_ID", referencedColumnName = "ID",
            updatable = false, insertable = false)
    public MealItem getMealItem() {
        return mealItem;
    }

    public void setMealItem(MealItem mealItem) {
        this.mealItem = mealItem;
    }

    @Transient
    public ArrayList<FoodItem> getFoodItems() {
        return foodItems;
    }

    public void setFoodItems(ArrayList<FoodItem> foodItems) {
        this.foodItems = foodItems;
    }

    @Transient
    public ArrayList<MealItem> getMealItems() {
        return mealItems;
    }

    public void setMealItems(ArrayList<MealItem> mealItems) {
        this.mealItems = mealItems;
    }

    public void makeDaysDate() throws ParseException{
        DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        this.daysDate = new Date(formatter.parse(this.daysDateString).getTime());
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof DayItem)) return false;

        DayItem dayItem = (DayItem) o;

        if (!getEmail().equals(dayItem.getEmail())) return false;
        if (!getModId().equals(dayItem.getModId())) return false;
        if (!getFmOrder().equals(dayItem.getFmOrder())) return false;
        return getDaysDate().equals(dayItem.getDaysDate());

    }

    @Override
    public int hashCode() {
        int result = getEmail().hashCode();
        result = 31 * result + getModId().hashCode();
        result = 31 * result + getFmOrder().hashCode();
        result = 31 * result + getDaysDate().hashCode();
        return result;
    }
}

这是添加DayItem的代码:

@Override
public List<DayItem> saveDayItem(DayItem item) throws Exception {
    List<DayItem> results = null;
    EntityManager manager = createEntityManager();
    EntityTransaction tx = manager.getTransaction();
    try {
        tx.begin();
        DayItem managedItem = manager.merge(item);
        manager.flush();
        manager.clear();
        tx.commit();
        results = findUserDay(managedItem.getDaysDate(), managedItem.getEmail(), manager);
    } catch (RuntimeException e) {
        tx.rollback();
        throw e;
    } finally {
        manager.close();
    }
    return results;
}

这是删除DayItems的代码:

public <T extends GtEntity> void batchDelete(List<T> entities) throws Exception {
    if (!entities.isEmpty()) {
        EntityManager manager = createEntityManager();
        EntityTransaction tx = manager.getTransaction();
        try {
            tx.begin();
            for (int i = 0; i < entities.size(); i++) {
                if (i % this.jdbcBatchSize == 0) {
                    manager.flush();
                    manager.clear();
                }

                T del = entities.get(i);
                T managed = manager.find((Class<T>)del.getClass(), del.getId());
                //The line above is where the problem happens

                manager.remove(managed);
            }
            manager.flush();
            manager.clear();
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e;
        }
    }
}

0 个答案:

没有答案