Data Jpa - операции с двумя аргументами

98
08 октября 2021, 07:00

Приложение на Spring Data Jpa. Имеется класс Meal. Имеется таблица meals, операции CRUD которой обрабатываются по двум параметрам - самого объекта Meal и Integer ID, который является foreign_key для связи таблиц meals и users.

Пример метода в репозитории(декларирую сам JpaRepository, дабы была возможность дэбажить):

@Autowired
private CrudMealRepository crudRepository;
@Override
public Meal save(Meal meal, int userId) {
    return crudRepository.save(meal);
}

Но текущая реализация метода мне не подойдет, потому что нигде не указано, как добавлять ID в таблицу для дальнейшей связи. Как решить данную задачу?

Meal

@SuppressWarnings("JpaQlInspection")
@NamedQueries({
        @NamedQuery(name = Meal.ALL_SORTED, query = "SELECT m FROM Meal m WHERE m.user.id=:userId ORDER BY m.dateTime DESC"),
        @NamedQuery(name = Meal.DELETE, query = "DELETE FROM Meal m WHERE m.id=:id AND m.user.id=:userId"),
        @NamedQuery(name = Meal.GET_BETWEEN, query = "SELECT m FROM Meal m " +
                "WHERE m.user.id=:userId AND m.dateTime BETWEEN :startDate AND :endDate ORDER BY m.dateTime DESC"),
//        @NamedQuery(name = Meal.UPDATE, query = "UPDATE Meal m SET m.dateTime = :datetime, m.calories= :calories," +
//                "m.description=:desc where m.id=:id and m.user.id=:userId")
})
@Entity
@Table(name = "meals", uniqueConstraints = {@UniqueConstraint(columnNames = {"user_id", "date_time"}, name = "meals_unique_user_datetime_idx")})
public class Meal extends AbstractBaseEntity {
    public static final String ALL_SORTED = "Meal.getAll";
    public static final String DELETE = "Meal.delete";
    public static final String GET_BETWEEN = "Meal.getBetween";
    @Column(name = "date_time", nullable = false)
    @NotNull
    private LocalDateTime dateTime;
    @Column(name = "description", nullable = false)
    @NotBlank
    @Size(min = 2, max = 120)
    private String description;
    @Column(name = "calories", nullable = false)
    @Range(min = 10, max = 5000)
    private int calories;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", nullable = false)
    @NotNull
    private User user;
    public Meal() {
    }
    public Meal(LocalDateTime dateTime, String description, int calories) {
        this(null, dateTime, description, calories);
    }
    public Meal(Integer id, LocalDateTime dateTime, String description, int calories) {
        super(id);
        this.dateTime = dateTime;
        this.description = description;
        this.calories = calories;
    }
    public LocalDateTime getDateTime() {
        return dateTime;
    }
    public String getDescription() {
        return description;
    }
    public int getCalories() {
        return calories;
    }
    public LocalDate getDate() {
        return dateTime.toLocalDate();
    }
    public LocalTime getTime() {
        return dateTime.toLocalTime();
    }
    public void setDateTime(LocalDateTime dateTime) {
        this.dateTime = dateTime;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public void setCalories(int calories) {
        this.calories = calories;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    @Override
    public String toString() {
        return "Meal{" +
                "id=" + id +
                ", dateTime=" + dateTime +
                ", description='" + description + '\'' +
                ", calories=" + calories +
                '}';
    }
}

User

@NamedQueries({
            @NamedQuery(name = User.DELETE, query = "DELETE FROM User u WHERE u.id=:id"),
            @NamedQuery(name = User.BY_EMAIL, query = "SELECT u FROM User u LEFT JOIN FETCH u.roles WHERE u.email=?1"),
            @NamedQuery(name = User.ALL_SORTED, query = "SELECT u FROM User u LEFT JOIN FETCH u.roles ORDER BY u.name, u.email"),
    })
    @Entity
    @Table(name = "users", uniqueConstraints = {@UniqueConstraint(columnNames = "email", name = "users_unique_email_idx")})
    public class User extends AbstractNamedEntity {
        public static final String DELETE = "User.delete";
        public static final String BY_EMAIL = "User.getByEmail";
        public static final String ALL_SORTED = "User.getAllSorted";
        @Column(name = "email", nullable = false, unique = true)
        @Email
        @NotBlank
        @Size(max = 100)
        private String email;
        @Column(name = "password", nullable = false)
        @NotBlank
        @Size(min = 5, max = 100)
        private String password;
        @Column(name = "enabled", nullable = false, columnDefinition = "bool default true")
        private boolean enabled = true;
        @Column(name = "registered", nullable = false, columnDefinition = "timestamp default now()")
        @NotNull
        private Date registered = new Date();
        @Enumerated(EnumType.STRING)
        @CollectionTable(name = "user_roles", joinColumns = @JoinColumn(name = "user_id"))
        @Column(name = "role")
        @ElementCollection(fetch = FetchType.EAGER)
        private Set<Role> roles;
        @Column(name = "calories_per_day", nullable = false, columnDefinition = "int default 2000")
        @Range(min = 10, max = 10000)
        private int caloriesPerDay = DEFAULT_CALORIES_PER_DAY;
        public User() {
        }
        public User(User u) {
            this(u.getId(), u.getName(), u.getEmail(), u.getPassword(), u.getCaloriesPerDay(), u.isEnabled(), u.getRegistered(), u.getRoles());
        }
        public User(Integer id, String name, String email, String password, Role role, Role... roles) {
            this(id, name, email, password, DEFAULT_CALORIES_PER_DAY, true, new Date(), EnumSet.of(role, roles));
        }
        public User(Integer id, String name, String email, String password, int caloriesPerDay, boolean enabled, Date registered, Collection<Role> roles) {
            super(id, name);
            this.email = email;
            this.password = password;
            this.caloriesPerDay = caloriesPerDay;
            this.enabled = enabled;
            this.registered = registered;
            setRoles(roles);
        }
        public String getEmail() {
            return email;
        }
        public void setEmail(String email) {
            this.email = email;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        public Date getRegistered() {
            return registered;
        }
        public void setRegistered(Date registered) {
            this.registered = registered;
        }
        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }
        public int getCaloriesPerDay() {
            return caloriesPerDay;
        }
        public void setCaloriesPerDay(int caloriesPerDay) {
            this.caloriesPerDay = caloriesPerDay;
        }
        public boolean isEnabled() {
            return enabled;
        }
        public Set<Role> getRoles() {
            return roles;
        }
        public String getPassword() {
            return password;
        }
        public void setRoles(Collection<Role> roles) {
            this.roles = CollectionUtils.isEmpty(roles) ? EnumSet.noneOf(Role.class) : EnumSet.copyOf(roles);
        }
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", email=" + email +
                    ", name=" + name +
                    ", enabled=" + enabled +
                    ", roles=" + roles +
                    ", caloriesPerDay=" + caloriesPerDay +
                    '}';
        }
    }
Answer 1

Не определено отношение @Onetomany

public class User extends AbstractNamedEntity {
    @OneToMany(mappedBy="user")
    private Set<Meal> meals;
}

И уберите @Enumerated с коллекции. Она для перечислений

READ ALSO
Ping-Pong на Java

Ping-Pong на Java

Доброго времени сутокПример из книги, символ в символ, но не работает, шарик не перемещается

78
Получение ANDROID_ID на всех версиях Android

Получение ANDROID_ID на всех версиях Android

Подскажите пожалуйста как в Android на всех версиях получать ANDROID_ID, чтобы для конкретного устройства он некогда не менялсяИ на другом устройстве...

110
Spring: как получить в Java-классе информацию о WildFly?

Spring: как получить в Java-классе информацию о WildFly?

Возникла необходимость получить в Java-классе информацию об инстансе WildFly, на котором развернуто приложение (в идеале - имя сервера, либо любую...

84