Не удалось установить значение поля путем отражения

У меня проблема с отношениями "многие ко многим". Таблицы: ингредиент и пищевая ценность. Я создал таблицу отношений между двумя объектами, в которой есть внешние ключи ингредиента и пищевой ценности (которые образуют составной ключ) и некоторые атрибуты.

Класс JoinedNutrionalValueIngredient:

import lombok.Data;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

@Entity @Data
public class JoinedNutrionalValueIngredient implements Serializable {

    @EmbeddedId
    private NutrionalValueIngredientId id;

    @ManyToOne(fetch= FetchType.LAZY)
    @MapsId("ingredient_id")
    private Ingredient ingredient;

    @ManyToOne(fetch=FetchType.LAZY)
    @MapsId("nutrional_value_id")
    private NutrionalValue nutrionalValue;

    @NotNull
    String matrixUnit;

    @NotNull
    int value;

    @NotNull
    String valueType;
}

Класс NutrionalValueIngredientId:

import javax.persistence.*;
import java.io.Serializable;
import java.util.Objects;

@Embeddable
@Getter
@Setter
public class NutrionalValueIngredientId implements Serializable{

    @Column(name = "ingredient_id")
    private Long ingredient_id;

    @Column(name = "nutrional_value_id")
    private Long nutrional_value_id;

    public NutrionalValueIngredientId() {
        
    }   
   
    public NutrionalValueIngredientId(Long ingredient, Long nutrionalValue){
        this.ingredient_id=ingredient;
        this.nutrional_value_id=nutrionalValue;
    }
    
    public boolean equals(Object o) {
        if (this == o) return true;
    
        if (o == null || getClass() != o.getClass())
            return false;
    
        NutrionalValueIngredientId that = (NutrionalValueIngredientId) o;
        return Objects.equals(ingredient_id, that.ingredient_id) &&
                    Objects.equals(nutrional_value_id, that.nutrional_value_id);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(ingredient_id, nutrional_value_id);
    }
}

Когда я пытаюсь вставить новое поле в таблицу отношений, я получаю эту ошибку:

{
  "timestamp": 1542653896247,
  "status": 500,
  "error": "Internal Server Error",
  "message": "Could not set field value [1] value by reflection : [class com.whateat.reciper.model.NutrionalValueIngredientId.ingredient_id] setter of com.whateat.reciper.model.NutrionalValueIngredientId.ingredient_id; nested exception is org.hibernate.PropertyAccessException: Could not set field value [1] value by reflection : [class com.whateat.reciper.model.NutrionalValueIngredientId.ingredient_id] setter of com.whateat.reciper.model.NutrionalValueIngredientId.ingredient_id",
  "path": "/v1/joinedNutrionalValueIngredients"
}

Обновлено: я добавил конструктор и аннотацию @Getter и @Setter, но у меня такая же ошибка.

класс NutritionalValue:

@Data
@Entity
public class NutrionalValue implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    private String name;

    @NotNull
    private String unit;

    @NotNull
    private String source;

    @ManyToOne
    @NotNull
    @JoinColumn(name = "category_id")
    private NutrionalValueCategory category;

    @OneToMany(mappedBy = "nutrionalValue")
    private Set<JoinedNutrionalValueIngredient> joined = new HashSet<JoinedNutrionalValueIngredient>();

}

редактировать: после ответа Debopam эта ошибка вылезла.

{
  "timestamp": 1542657216244,
  "status": 500,
  "error": "Internal Server Error",
  "message": "null id generated for:class com.whateat.reciper.model.JoinedNutrionalValueIngredient; nested exception is org.hibernate.id.IdentifierGenerationException: null id generated for:class com.whateat.reciper.model.JoinedNutrionalValueIngredient",
  "path": "/v1/joinedNutrionalValueIngredients"
}

Ваши поля NutrionalValueIngredientId защищены пакетом, вам нужно сделать их частными и добавить геттеры / сеттеры (вручную (например, с помощью генератора ide)) или использовать lombok.

Victor Gubin 19.11.2018 20:12

Я пробовал, но получаю ту же ошибку.

Francesco 19.11.2018 20:27

Еще одна вещь, вы забыли добавить требуемый конструктор по умолчанию. Проверить это

Victor Gubin 19.11.2018 20:32

Не могли бы вы поделиться классом NutritionalValue

Mykhailo Moskura 19.11.2018 20:36
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
5
4
16 830
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Измените имена переменных, как показано ниже

Длинный ингредиент_ид в Длинный ингредиентид nutrional_value_id в nutrionalvalueid

Пример

  @Column(name = "ingredient_id")
  Long ingredient_id;

к

@Column(name = "ingredient_id")
Long ingredientid;

Затем сгенерируйте геттер-сеттер для всех полей. Hibernate не может установить поля, потому что нет общедоступного получателя / установщика.

Спасибо за ответ. Я изменил названия переменных, теперь получил еще одну ошибку.

Francesco 19.11.2018 21:13

Задайте значения для идентификатора объекта «NutrionalValueIngredientId», затем попробуйте вставить его как встроенный идентификатор для «JoinedNutrionalValueIngredient». см. пример ниже:

package com.example;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;

@Embeddable
public class EmployeeId implements Serializable
{
private static final long serialVersionUID = 1L;
@Column(name = "EMP_ID")
private int empId;
@Column(name = "DEPARTMENT")
private String department;

public EmployeeId()
{
    super();
}
public EmployeeId(int empId, String department)
{
    super();
    this.empId = empId;
    this.department = department;
}

public int getEmpId()
{
    return empId;
}
public void setEmpId(int empId)
{
    this.empId = empId;
}
public String getDepartment()
{
    return department;
}
public void setDepartment(String department)
{
    this.department = department;
}
@Override
public int hashCode()
{
    final int prime = 31;
    int result = 1;
    result = prime * result + ((department == null) ? 0 : department.hashCode());
    result = prime * result + empId;
    return result;
}
@Override
public boolean equals(Object obj)
{
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    EmployeeId other = (EmployeeId) obj;
    if (department == null)
    {
        if (other.department != null)
            return false;
    } else if (!department.equals(other.department))
        return false;
    if (empId != other.empId)
        return false;
    return true;
}
 }

См. Выше Embedded Id class (EmployeeId). который является первичным ключом класса Employee. Итак, нам нужно установить значения в классе Id (EmployeeId). Затем ввести этот класс идентификатора в Employee в качестве первичного ключа. Тогда все заработает. Без первичного ключа это значение равно нулю.

package com.example;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Employee implements Serializable
{
private static final long serialVersionUID = 1L;
@EmbeddedId
EmployeeId id;
@Column(name = "EMP_NAME")
private String empName;

public Employee()
{
    super();
}
public Employee(EmployeeId id, String empName)
{
    super();
    this.id = id;
    this.empName = empName;
}
public EmployeeId getId()
{
    return id;
}
public void setId(EmployeeId id)
{
    this.id = id;
}
public String getEmpName()
{
    return empName;
}
public void setEmpName(String empName)
{
    this.empName = empName;
}
} 

Задайте значения для класса Id и другого поля, как показано ниже.

 //Create a new Employee object   
 Employee employee = new Employee();

 EmployeeId employeeId = new EmployeeId(1,"DailyNews");
 employee.setEmpName("CompositeKey");
 employee.setId(employeeId);

 session.save(employee);

При использовании Spring Data Rest автоматически генерировались необработанные операции. однако предложенное нам решение заставило бы меня переписать метод публикации. что я хотел бы сделать, так это вставить эту таблицу непосредственно из вызова rest. @Roshini

Francesco 20.11.2018 19:39

Убедитесь, что вы устанавливаете экземпляр для встроенного идентификатора. У меня не было этой ошибки.

Я меняю это

@EmbeddedId
ProductUserId id;    

ProductUser(Integer productId, Integer UserId, Double rating){
    this.rating = rating
}

к

@EmbeddedId
ProductUserId id;    

ProductUser(Integer productId, Integer userId, Double rating){
    this.id = new ProductUserId(productId, userId);
    this.rating = rating
}
 @Entity @Data
 public class JoinedNutrionalValueIngredient implements Serializable {
    
        @EmbeddedId
        private NutrionalValueIngredientId id = new NutrionalValueIngredientId();
    
    // ... rest of class  
 }

В классе JoinedNutrionalValueIngredient должен быть инстанциирован идентификатор соединения NutrionalValueIngredientId .

Это то, что мне пришлось сделать. Я заполнял свой эквивалент «ингридиента» и «нутрионального значения» и получал исключение «Не удалось установить поле ...» при сохранении. Для меня проблема была решена.

Mat 08.07.2021 11:45

Другие вопросы по теме