使用嵌入式模型的Spring Boot Hibernate ManyToMany Relation

Ehsan Sasanian:

我有一个关于ManyToMany实现的问题。假设我们有两个模型域,例如Menu和RoleGroup,我的Menu模型包括一个名为@@ ManyToMany的“ Private RoleGroup roleGroup”字段和带有JoinColumns和InverseJoinColumns的@JoinTable字段。想象一下,我已经创建了一个像Menu这样的对象,其中包含RoleGroup字段,并且在数据库中保存了entityRepository .save这是我的问题,有没有办法在不使用本机查询的情况下更新我的对象(考虑到ManyToMany关系)?因为当我们使用ManyToMany关系时,hibernate通过在数据库中创建第三个表(例如“ Menu_RoleGroup”)来处理它,因为我们没有像Menu_RoleGroup这样的域。

//这是我的应用程序

   package org.sayar.layout.domain;

    import java.util.HashSet;
    import java.util.Set;

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.JoinColumn;




    import javax.persistence.JoinTable;
    import javax.persistence.ManyToMany;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;

    import org.hibernate.annotations.Nationalized;
    import org.sayar.layout.base.general.domain.GeneralDomain;
    import org.sayar.layout.constants.SchemaList;
    import org.sayar.layout.domain.uaa.Role;
    import org.sayar.layout.domain.uaa.RoleGroup;
    import org.springframework.data.annotation.Transient;

    import com.fasterxml.jackson.annotation.JsonInclude;
    import com.fasterxml.jackson.annotation.JsonManagedReference;

    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;

    /**
     * This domain for store and transfer Menu
     *
     * @author Ehsan
     */
    @Setter
    @Getter
    @AllArgsConstructor
    @NoArgsConstructor
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @Entity(name = Menu.TABLE_NAME)
    @Table(name = Menu.TABLE_NAME, schema = SchemaList.LAYOUT)
    public class Menu extends GeneralDomain {
        @Transient
        public final static String TABLE_NAME = "Menu";


        public class CN {
            public final static String title = "title";
            public final static String description = "description";
            public final static String banner = "banner";
        }

        @Nationalized
        @Column(name = CN.title, length = 128, nullable = false)
        private String title;

        @Nationalized
        @Column(name = CN.description, length = 1000)
        private String description;

        @Nationalized
        @Column(name = CN.banner, length = 128)
        private String banner;

        /* Relationships */

        @ManyToMany(fetch = FetchType.EAGER)
        @JoinTable(name = "Menu_RoleGroup",
                schema = SchemaList.LAYOUT,
                joinColumns = @JoinColumn(name = "menuId", referencedColumnName = GCN.id), //
                inverseJoinColumns = @JoinColumn(name = "roleGroupId", referencedColumnName = GCN.id))
        private Set<RoleGroup> roleGroupSet;

        @OneToMany(mappedBy = MenuItem.CN.menu, fetch = FetchType.EAGER)
        @JsonManagedReference
        private Set<MenuItem> menuItemSet = new HashSet<>();

        /* Constructors */
        public Menu(String title, String banner, String description) {
            this.title = title;
            this.banner = banner;
            this.description = description;
        }

        public Menu(String title, String banner, String description, Set<RoleGroup> roleGroupSet) {
            this.title = title;
            this.banner = banner;
            this.description = description;
            this.roleGroupSet = roleGroupSet;
        }

        public Menu(String id) {
            super(id);
        }
        /* Other classes or enumerations */

    }
    .
    .
    .
    .
    .

    package org.sayar.layout.domain.uaa;

    import java.util.Date;

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.EnumType;
    import javax.persistence.Enumerated;
    import javax.persistence.Table;

    import org.hibernate.annotations.Nationalized;
    import org.sayar.layout.base.general.domain.GeneralDomain;
    import org.sayar.layout.constants.SchemaList;
    import org.springframework.data.annotation.Transient;

    import com.fasterxml.jackson.annotation.JsonInclude;

    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    import lombok.Setter;

    /**
     * This domain for store and transfer RoleGroup
     *
     * @author Ehsan
     *
     */
    @Setter
    @Getter
    @AllArgsConstructor
    @NoArgsConstructor
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @Entity(name = RoleGroup.TABLE_NAME)
    @Table(name = RoleGroup.TABLE_NAME, schema = SchemaList.UAA)
    public class RoleGroup extends GeneralDomain {
        @Transient
        public final static String TABLE_NAME = "RoleGroup";

        public class CN {
            public final static String title = "title";
            public final static String status = "status";
        }

        @Nationalized
        @Column(name = CN.title, length = 128, nullable = false)
        private String title;

        @Enumerated(EnumType.STRING)
        @Column(name = CN.status, nullable = false)
        private Status status;

        public RoleGroup(String id) {
            super(id);
        }

        /* Relationships */
        /* Constructors */
        /* Other classes or enumerations */
        public enum Status {
            ACTIVE, DE_ACTIVE
        }
    }
    .
    .
    .
    package org.sayar.layout.service.menu;

    import org.sayar.layout.base.util.Print;
    import org.sayar.layout.domain.Menu;
    import org.sayar.layout.repository.megaitem.MegaItemRepository;
    import org.sayar.layout.repository.menu.MenuRepository;
    import org.sayar.layout.repository.menuitem.MenuItemRepository;
    import org.sayar.layout.rest.menu.dto.*;
    import org.springframework.stereotype.Service;
    import org.sayar.layout.dao.menu.MenuDaoImpl;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    import org.springframework.http.ResponseEntity;

    import java.util.List;

    import lombok.RequiredArgsConstructor;
    import org.springframework.transaction.annotation.Transactional;
    import reactor.core.publisher.Mono;

    /**
     * Spring service implementation for the Menu entity.
     *
     * @author Ehsan
     */
    @Service
    @RequiredArgsConstructor
    public class MenuServiceImpl implements MenuService {

        private final MenuDaoImpl entityDao;
        private final MenuRepository entityRepository;
        private final MenuItemRepository menuItemRepository;
        private final MegaItemRepository megaItemRepository;

        @Override
        public Mono<ResponseEntity<Boolean>> create(ReqMenuCreateDTO entity, String userId) {
            return Mono.just(entityRepository.save(entity.map(userId)))
                    .flatMap(createdEntity -> Mono.just(ResponseEntity.ok().body(true))
                    )
                    .defaultIfEmpty(ResponseEntity.ok().body(false));
        }

        @Transactional
        @Override
        public Mono<ResponseEntity<Boolean>> update(String id, ReqMenuUpdateDTO entity) {

            Mono.just(entityRepository.update(id, entity.getTitle(), entity.getBanner(), entity.getDescription())).subscribe();
            Mono.just(entityRepository.deleteRoleMenu(id)).subscribe();
            Print.print("title", entity);

            if (entity.getRoleGroupIdSet() != null && !entity.getRoleGroupIdSet().isEmpty())
                for (String roleId : entity.getRoleGroupIdSet()) {
                    Mono.just(entityRepository.updateRoleMenu(id, roleId)).subscribe();
                }
            return Mono.just(ResponseEntity.ok().body(true));

        }
    .
    .
    .
    .
    .
    package org.sayar.layout.repository.menu;


    import org.sayar.layout.constants.SchemaList;
    import org.sayar.layout.repository.menu.dto.ResRoleGetListRepoDTO;
    import org.sayar.layout.rest.menu.dto.ResMenuGetListDTO;
    import org.sayar.layout.repository.menu.dto.ResMenuGetOneRepoDTO;
    import org.sayar.layout.rest.menu.dto.ResMenuGetOneDTO;
    import org.sayar.layout.rest.menu.dto.ResMenuGetPageDTO;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;

    import java.util.List;
    import java.util.Optional;

    import org.sayar.layout.domain.Menu;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.jpa.repository.Modifying;
    import org.springframework.data.jpa.repository.Query;
    import org.springframework.data.repository.query.Param;
    import org.springframework.transaction.annotation.Transactional;

    /**
     * Spring Data SQL Server repository for the Menu entity.
     *
     * @author Ehsan
     */
    @Repository
    public interface MenuRepository extends JpaRepository<Menu, String> {

        //  UPDATE ALL STARTS HERE
        @Transactional
        @Modifying
        @Query(value = "UPDATE Menu AS m SET m.title = :title , m.description = :description, m.banner = :banner WHERE m.id = :id")
        Integer update(@Param("id") String id, @Param("title") String title, @Param("description") String description, @Param("banner") String banner);

        @Transactional
        @Modifying
        @Query(value = "DELETE FROM layout.Menu_RoleGroup WHERE menuId = :id", nativeQuery = true)
        Integer deleteRoleMenu(@Param("id") String id);

        @Transactional
        @Modifying
        @Query(value = "INSERT INTO layout.Menu_RoleGroup (menuId,roleGroupId) VALUES (:menuId,:roleGroupId)", nativeQuery = true)
        Integer updateRoleMenu(@Param("menuId") String menuId, @Param("roleGroupId") String roleGroupId);
    }
Ehsan Sasanian:

其实我知道如何解决!在这种情况下,我必须创建一个像MenuRoleGroup这样的域模型作为实体,然后添加一个Embeddable字段(例如MenuRoleGroupEmbeddable),并在MenuRoleGroup中使用create @EmbeddedId字段。然后在MenuRoleGroupEmbeddable中添加Menu和RoleGroup的主键。

因此,Spring Data能够创建MenuRoleGroupRepository来扩展JPA Repository,但是请注意,该表具有两个主键,而不是一个。

请注意,MenuRoleGroup中的MenuRoleGroupEmbeddable字段没有关系,但是Menu和RoleGroup与MenuRoleGroupEmbeddable模型都具有@ManyToOne关系。

这是例子。

package org.sayar.wms.domain.Menu;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.GenericGenerator;
import org.sayar.wms.base.general.domain.GeneralDomain;
import org.sayar.wms.constants.SchemaList;
import org.sayar.wms.domain.container.Container;
import org.sayar.wms.domain.product.ProductContainerEmbeddable;
import org.springframework.data.annotation.Transient;

import javax.persistence.*;
import java.util.Date;


@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@Entity(name = MenuRoleGroup.TABLE_NAME)
@Table(name = MenuRoleGroup.TABLE_NAME, schema = SchemaList.WMS)
public class MenuRoleGroup {

    @Transient
    public final static String TABLE_NAME = "MenuRoleGroup";

    public class CN {
        public final static String startDate = "startDate";
    }

    @EmbeddedId
    private MenuRoleGroupEmbeddable menuRoleGroupEmbeddable;

    @JoinColumn(name = CN.startDate, referencedColumnName = GeneralDomain.GCN.id)
    private Date startDate;

}


package org.sayar.wms.domain.Menu;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.sayar.wms.base.general.domain.GeneralDomain;
import org.sayar.wms.domain.container.Container;

import javax.persistence.CascadeType;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import java.io.Serializable;
import java.util.Set;

/**
 * This domain for store and transfer Warehouse
 *
 * @author masoud
 */
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@Embeddable
public class ProductContainerEmbeddable implements Serializable {

    public class CN {
        public final static String menuId = "menuId";
        public final static String roleGroupId = "roleGroupId";
    }

    /* Relationships */

    @ManyToOne
    @JoinColumn(name = CN.menu, referencedColumnName = "id")
    private Menu menu;

    @ManyToOne
    @JoinColumn(name = CN.roleGroup, referencedColumnName ="id")
    private RoleGroup roleGroup;

    /* Constructors */


    /* Other classes or enumerations */

}

menuId和roleGroupId都是MenuRoleGroup实体的主键。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Spring Hibernate双向ManyToMany StackOverflowError

Hibernate中的ManyToMany映射引用错误(api生成的表名)表Spring Boot

在Spring Boot中使用多个嵌入式数据存储

使用Spring Boot的MongoDB嵌入式文档

将Spring Boot Weblfux与嵌入式Tomcat结合使用

Spring Boot数据嵌入式Cassandra

用于Spring Boot的嵌入式Redis

Spring Boot嵌入式tomcat日志

Spring Boot + GWT嵌入式配置

Spring Boot嵌入式Tomcat性能

Spring Boot JPA ManyToMany导致OutOfMemoryError

Spring Boot ManyToMany-StackOverflow-JPA,休眠

Spring Boot ManyToMany精确嵌套的数据

Spring Boot中的ManyToMany映射问题

Spring boot :Hibernate 注解

使用Spring MVC,JPA和Hibernate添加ManyToMany

无法使用嵌入式 Tomcat 浏览到 Spring Boot 应用程序

如何使用嵌入式Tomcat 8和Spring Boot将子域转换为路径

使用application.yml在Spring Boot中配置嵌入式Tomcat的日志记录

使用嵌入式容器和JNDI运行Spring Boot应用

使用Spring Boot和嵌入式驱动程序测试Neo4j

使用IntelliJ部署支持嵌入式tomcat的spring-boot应用程序

如何使用Spring Boot配置嵌入式ActiveMQ Broker URL

使用Spring Boot在嵌入式Tomcat服务器上部署资源

与 SpringBootTest 一起使用时,Spring Boot 嵌入式 Tomcat 无法启动

如何使用Spring Boot和嵌入式Tomcat配置此属性?

使用Spring Boot和嵌入式Tomcat启用会话持久性

如何使用Spring Boot应用程序在嵌入式Jetty中配置异步超时

使用黄瓜时,Spring Boot在嵌入式Cassandra之前加载,我该如何解决?