Ответы пользователя по тегу Hibernate
  • Возможно ли связывание сущностей через интерфейс в Spring JPA?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день
    Важный момент почему вы решили использовать интерфейс для связки сущностей?
    Вы например, можете создать абстрактный класс и расширить его классами Dog, Cat и т.д.
    Т.е. создаете абстрактный класс Animal. (Обратите внимание на `@Inheritance` )
    А дальше расширяете этот класс другими классами. Ну и связываете Animal с нужными сущностями
    https://www.baeldung.com/hibernate-inheritance
    Ответ написан
  • Почему при выводе на форму не подтягивается связанный объект из БД?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день.

    @OneToOne(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
        @JoinColumn(name = "id")
        private UserInfo userInfo;


    Так у вас FetchType.LAZY, потому данные и не подтягиваются. А OSIV у вас включен или отключен?

    P.S. не передавайте на фронт саму сущность. Используйте DTO.
    Ответ написан
    2 комментария
  • JpaRepository: как убрать избыточный джойн в поиске при использовании entitygraph?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день.
    EntityGraph сам по себе ничего не делает. Это уже поднаготная самого Hibernate.
    https://stackoverflow.com/questions/26769989/hiber...

    Может какой то параметр есть для этого или аннотация?

    Такого параметра нет.

    Вот, полезная статья по этой теме - https://thorben-janssen.com/5-common-hibernate-mis...

    Для поиска я бы рекомендовал использовать Specification<T> & Criteria API. А на больших проектах тут уже использовать Hibernate Search, ElasticSearch, Apache Lucene
    Ответ написан
    Комментировать
  • Как можно избежать написания большого количества функций репозитория?

    azerphoenix
    @azerphoenix
    Java Software Engineer
    Добрый день.
    Если речь идет о поиске данных в БД и об уменьшении кол-ва кода, т.е. именованных методов, то можете использовать следующие решения
    1 - Используйте спецификации. Создайте список предикатов и уже по ним проводите поиск в БД.
    Простой пример
    public Specification<User> applicationSpecification(
              // search arguments
    ) {
        return (root, query, criteriaBuilder) -> {
          List<Predicate> predicates = new ArrayList<>();
          if (StringUtils.isNotBlank(status)) {
            Predicate predicate = criteriaBuilder.like(// Your code here);
            predicates.add(predicate);
          }
          // other search conditions
          return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
      }

    2 - Используйзет готовые библиотеки. Например, https://github.com/tkaczmarzyk/specification-arg-r...
    Ответ написан
    Комментировать
  • Как создавать связанные сущности через RESTController?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день.
    Начнем с самого начала.
    Рекомендую в первую очередь реализовать энтерпрайз паттерн DTO.
    Создаете модель, которая описывает вашу сущность и которую планируете получать в контроллере для создания и отправлять ответ после создания.
    Желательно называть их понятным образом.
    Допустим, у вас есть entity - Event. EventCreationRequest, EventCreationResponse, EventDTO, EventUpdatingRequest и т.д.
    Конечно же, вам нужно маппить данные между Event -- EventDTO.
    Можно по-разному реализовать.
    Есть готовые либы - MapStruct, ModelMapper, JMapper и др. Я предпочитаю использовать MapStruct или ModelMapper.
    https://www.baeldung.com/spring-type-conversions
    Если не хотите либу, то используйте интерфейс Converter<S,T> содержащийся в Spring. Он принимает 2 дженерика - source & target.
    Например,
    EventDTOMapper implements Converter<EventDTO, Event>

    Отмечу, что для nested classes тоже стоит создать DTO.

    Далее касаемо @PostMapping("") можно не указывать скобки, а просто @PostMapping.

    return ResponseEntity(created, HttpStatus.OK)
    можно более сокращенно ResponseEntity.ok(created);

    Следуя документации, hibernate должен сам подтягивать по id нужный Subject из бд, но он этого не делает, ругаясь на отсутствие конструктора.

    Отмечу, что каждая сущность должна иметь коструктор без аргументов.
    В kotlin для spring есть соответствующие плагины, которые нужно подключать. (читаем документацию)
    Ответ написан
    Комментировать
  • Hibernate не видит entity. Как пофиксить?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый вечер.
    А кто пропишет в файл конфигурации, что этот класс является entity?)

    Обратите внимание на эту строку -
    <mapping class="hibernate.entity.User"/>

    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD//EN"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
        <session-factory>
            <property name="connection.url">jdbc:mysql://localhost:3306/spring_course</property>
            <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="connection.username">root</property>
            <property name="connection.password">springcourse</property>
            <property name="current_session_context_class">thread</property>
            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
            <property name="show_sql">true</property>
           
             <mapping class="hibernate.entity.User"/>
        </session-factory>
    </hibernate-configuration>
    Ответ написан
  • Hibernate не видит entity?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Недавно столкнулся с похожей ситуацией, когда один и тот же проект работал на моем ноуте, а в ноуте коллеги нет. Там правда, была проблема в rabbitmq.
    Как именно вы поднимаете БД? Если в докере, то попробуйте разные образы. Проверьте создается ли БД, есть ли нужные привилегии у пользователя и т.д. Может быть проблема даже не в коде...
    Ответ написан
    Комментировать
  • Как обновить большие данные в Hibernate?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день.
    Читать все данные из БД разом в List<Foo> или любую другую коллекцию не самая лучшая идея.
    Соответственно, можно вместо коллекций использовать стримы.
    Т.е. Получить Stream<Foo>

    Пример,
    FooRepository {
    
    @QueryHints(value = {
                @QueryHint(name = HINT_FETCH_SIZE, value = "1000"),
                @QueryHint(name = HINT_CACHEABLE, value = "false"),
                @QueryHint(name = READ_ONLY, value = "true")
        })
        @Query(value = "SELECT DISTINCT f FROM Foo f")
        @Transactional(readOnly = true)
        Stream<Foo> findFoos();
    
    }


    Ну а дальше остается распараллелить стрим при помощи parallelStream()
    И произвести необходимые операции. Например, вызвать метод map() и в конце сохранить...

    Если нужно данную операцию производить периодически, то к методу, который будет производить операцию, добавьте @Async и используйте @Scheduled (или возможности Spring Batch, Spring Quartz)

    Для более подробного ответа нужно больше информации.
    Ответ написан
  • Как лучше хранить данные в MySQL для проекта Java?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день.
    Как вариант вы можете хранить данные в виде json. Есть либа для hibernate - hibernate types

    Но т.к. могут быть разные шаблоны html, то невозможно хранить данные для заполнения в одном конкретном классе.

    Так не храните в конкретном классе. Создайте 1 общий родительский класс с общими полями. А также необходимые дочерние классы (по 1 на каждый шаблон).
    А далее используйте https://www.baeldung.com/hibernate-inheritance

    Краткий принцип работы: происходит добавления емейла в очередь в БД, через некоторое время специальный сервис отправляет это сообщение.

    Я так понимаю, что это некий amqp сервис (rabbitmq, kafka и др), который слушает event и пр наличии отправляет майл?
    Ответ написан
    Комментировать
  • Spring JPA, как обновить данные в модальном окне?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    th:href="@{findOne/(id=${tour.id})}"
    Глянув на этот участок кода могу сказать следующее - не передавайте саму сущность на фронт. Вместо этого используйте паттерн DTO. Т.е. для создания / обновления используйте DTO, который затем в сервисном слое маппите в entity и сохраняете в БД,
    Для маппинга можно использовать разные либы.
    Например, интерфейс Converter<S, T> или же либу MapStruct, ModelMapper и др.
    Также можно использовать BeanUtils.copyProperties() например, для обновления сущности.

    @ResponseBody
        public Tour findOne(Integer id) {
            return tourRepository.findById(id).get();
        }

    Вместо get() лучше использовать например, orElseThrow() и выбросить исключение, которое впоследствиее можно при помощи ExceptionHandler обработать и вернуть корректный http ответ. Например, когда объект не найден (404)

    @Autowired
        private TourRepository tourRepository;
        @PostMapping("/save")
        public String save(@ModelAttribute(name = "tour") Tour tour) {
            tourRepository.save(tour);
            return "redirect:/";
        }
        @PostMapping("/admin/saveTour")
        public String saveTourInModal(@ModelAttribute(name = "tour") Tour tour) {
            tourRepository.save(tour);
            return "redirect:/admin/tourList";
        }

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

    Само модальное окно вызывается и заполняется данными объекта. После нажатия на кнопку сохранения, у меня стало выводить исключение org.hibernate.exception.ConstraintViolationException: could not execute statement, и что поля бд title и description не могут быть null.

    Вопрос в том, почему они были null, если вы делаете сабмит формы. Попробуйте глянуть в консоли браузера во вкладке "Сеть", какие именно данные отправляются в бэк. Также в режиме дебага проверьте, что именно вы принимаете и сохраняете в БД.

    Обратите внимание, что на одной странице вы делаете update
    Hibernate: update tour set description=?, end_time=?, image=?, price=?, start_time=?, title=? where code=?

    А на другой странице insert
    Hibernate: insert into tour (description, end_time, image, price, start_time, title) values (?, ?, ?, ?, ?, ?)


    Для более точного ответа нужен исходник проекта, ибо я не вижу кода сущности
    Ответ написан
    Комментировать
  • Как обновит массив объектов в spring boot?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день.
    Ну во-первых, вам не нужно итерировать по старой и новой коллекции.
    Вы можете либо воспользоваться методом addAll(). либо же раз решили итерировать, то
    создать методы add() и remove()
    Прочитайте эту статью:
    https://vladmihalcea.com/the-best-way-to-map-a-one...
    Для более полного ответа нужно увидеть весь код. Например, вы указали вот, эту строку в комментарии:
    List<Address> addressList = oldUser.getAddress()
    Тут либо действительно проблема. либо метод назван неправильно, так как getAddress() подразумевает получение одного адреса, а не списка адресов пользователя. Должно быть getAddresses(), ну а метод getAddress() должен возвращать 1 адрес
    Рекомендую поставить брейкпоинты и провести дебаг
    Ответ написан
    Комментировать
  • Как одну сущность использовать в нескольких таблицах?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Добрый день.
    Было бы неплохо увидеть стек.
    А так попробуйте:

    class Rate {
    
    	@ManyToOne(fetch = FetchType.LAZY)
        private Tarif tarif;
    
        @ManyToOne(fetch = FetchType.LAZY)
        private TarifGarant tarifGarant;
    }
    
    class Tarif {
    
    	@OneToMany(
            mappedBy = "tarif",
            cascade = CascadeType.ALL,
            orphanRemoval = true
        )
        private List<Rate> rates;
    
    }
    
    class TarifGarant {
    
    	@OneToMany(
            mappedBy = "tarifGarant",
            cascade = CascadeType.ALL,
            orphanRemoval = true
        )
        private List<Rate> rates;
    }
    Ответ написан
  • Почему возникает org.springframework.beans.factory.UnsatisfiedDependencyException, при попытке подключения к PostgreSQL?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день.
    Уберите:
    <!-- https://mvnrepository.com/artifact/org.hibernate.orm/hibernate-core -->
        <dependency>
          <groupId>org.hibernate.orm</groupId>
          <artifactId>hibernate-core</artifactId>
          <version>6.0.0.Final</version>
        </dependency>
     <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
        <dependency>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-entitymanager</artifactId>
          <version>5.6.8.Final</version>
        </dependency>


    Также вы можете удалить version отсюда:
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-jpa</artifactId>
          <version>2.6.6</version>
        </dependency>


    Попробуйте перезапустить приложение. Вот. похожая проблема: https://stackoverflow.com/questions/42182426/sprin...
    Ответ написан
    Комментировать
  • Можно ли в Hibernate одна таблица унаследовало ID второй таблицы?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день.
    Так может быть вам не нужна связь OneToOne, а нужна @Embeddable для Activity и вместо связи OneToMany для List использовтаь @ElementCollection или @CollectionOfElements для List<Address>
    https://stackoverflow.com/questions/8969059/differ...
    https://www.baeldung.com/jpa-embedded-embeddable
    Если вы хотите встроить ID, то наверное можно глянуть на @EmbeddedId https://www.baeldung.com/spring-jpa-embedded-metho...
    Ответ написан
    Комментировать
  • Как из вложенных объектов в классе сделать одну таблицу?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день.
    Ответ - никак.
    Как вы сами сказали, это объекты. А значит, их значения будут хранится в других таблицах. А этот объект при помощи foreign key будет ссылаться на вложенный объект.

    Есть правда, следующий вариант (если он вам подойдет):
    Если объект может быть встроенным, то вы можете вместо сущности использовать аннотации @Embeddable & @Embedded
    https://www.baeldung.com/jpa-embedded-embeddable
    Т.е. по факту колонки встраиваемого объекта будут добавлены к основной сущности

    P.S. есть еще один вариант реализации вашей задумки. Возможно, что не самый лучший.
    В общем, если вы используете БД postgres, то объект можно хранить в формате jsonb.
    Из коробки решения нет, но можно подключить доп. либу.
    Вот, похожий вопрос:
    https://stackoverflow.com/questions/51276703/how-t...

    Зависимость:
    <dependency>
        <groupId>com.vladmihalcea</groupId>
        <artifactId>hibernate-types-52</artifactId>
        <version>2.2.2</version>
    </dependency>


    @Type(type = "jsonb")
        @Column(columnDefinition = "jsonb")
        private List<Child> children;


    На мой взгляд, лучше не заморачиваться так. Имхо, правильнее создавать отдельные таблицы.
    Ответ написан
    1 комментарий
  • Какие отношения должны быть между этими двумя Entity?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Нечто похожее уже обсуждалось в данном вопросе:
    https://qna.habr.com/q/1111518

    Допустим, что у вас есть сущность Product, а также сущность Order.
    В одном заказе может быть некоторое кол-во одного товара, а значит, вам где-то нужно хранить еще и кол-во заказанного товара.
    Для этого подойдет аггрегация, как вариант.
    Т.е. нужно завести доп. таблицу (например, OrderData), в которой foreign_keys будут являться и product_id и order_id, а также будет. доп. колонка quantity.
    +----------+------------+----------+
    | order_id | product_id | quantity |
    +----------+------------+----------+
    |        1 |          2 |       10 |
    |        2 |          3 |       11 |
    +----------+------------+----------+


    Таким образом, у вас должно получится что-то типа такого (псевдокод):
    Product {
    long productId;
    }
    Order {
    long orderId;
    }
    OrderData {
    Order order;
    Product product;
    int quantity;
    }


    Другой вариант:
    это как указано в вопросе по ссылке выше. Использовать мапу.
    Привожу ссылку на полезный ресурс:
    https://www.baeldung.com/hibernate-persisting-maps
    Что в данном случае должно получиться (псевдокод):
    Product {
    long productId;
    }
    
    Order {
    
    @MapKeyColumn(name = "product_id")
    @Column(name = "quantity")
    Map<Long, Integer>
    }


    В данном случае, мы указываем на MapKeyColumn. Т.е. уник. ключом будет являться идентификатор продукта. А значением будет его кол-во (название указано в Column).

    Наверняка, если подумать еще, то можно найти еще варианты.
    Ответ написан
    Комментировать
  • Как правильно аннотировать @OneToMany, когда используем map в данном случае?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день.
    Вот, есть наглядная статья по вашему вопросу:
    https://www.baeldung.com/hibernate-persisting-maps
    Ответ написан
    4 комментария
  • Как использовать методы при @ManyToOne связи в рамках JpaRepository?

    azerphoenix
    @azerphoenix Куратор тега Spring
    Java Software Engineer
    Вам просто необходимо вызвать метод void addArticleToAuthor(Article article)
    А в конце вызвать метод author.save()
    Вот, полезная ттатья по ManyToOne & OneToMany
    https://thorben-janssen.com/best-practices-many-on...
    https://www.baeldung.com/hibernate-one-to-many
    Ответ написан
    Комментировать
  • CRUD spring+hibernate: передача json и обработка на сервере?

    azerphoenix
    @azerphoenix Куратор тега Java
    Java Software Engineer
    Добрый день.
    По-первых, для реализации вашей задачи вам необходимо обратить внимание на паттерно DTO (data to object).
    Также, если у вас приложение на Spring, то можете подключить мапперы для удобства маппинга (конвертации) dto -> entity (и наоборот). Можете использовать такие либы, как modelMapper, MapStruct.
    Если не хотите использовать либу, то имплементируйте интерфейс Converter<S,T>

    Оптимальность, чтобы не надо было передавать лишних полей, если они не заносятся в таблицу или автогенерируются

    Вы можете на клиентской стороне средствами js проверить поля объекта на null и в случае оного просто не передавать это поле. Ну или же можно передать это поле и проверить на null & empty уже на серверной стороне.

    В JSON в поле one-to-many (например при создании юзера у него будут животные) чтобы передавался только массив idшников животных, а не полностью вся информация о них (частично пересекается с первым пунктом - оптимальность)

    Чтобы передать id животного/ных из фронта необходимо, чтобы они были в БД. Если животные добавляются раньше пользователя, то достаточно при получении dto для user (в утильном классе Converter) найти животных по переданным id и назанчить этих животных юзеру через setPets()или метод addPet()
    Ответ написан
    Комментировать