RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1115338
Accepted
Antonio112009
Antonio112009
Asked:2020-04-25 05:56:04 +0000 UTC2020-04-25 05:56:04 +0000 UTC 2020-04-25 05:56:04 +0000 UTC

如何使用附加列制作多对多?

  • 772

这个想法很简单:我想创建一个 ManyToMany 依赖项,但有一个额外的列。

在我的项目中,我使用Project Lombok,因此@Data取代了我Getter/Setter/ToString/Equals/Hash.

我的想法 100% 类似于:https ://vladmihalcea.com/the-best-way-to-map-a-many-to-many-association-with-extra-columns-when-using-jpa-and- hibernate/ 但是,这个选项对我不起作用

实体关系图:

在此处输入图像描述

测试程序时出现错误:

Caused by: java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails 
   (`dishdatabase`.`dish_size`, CONSTRAINT `FKqpfda2uojtpf1u243dy0e55fq` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`))


更新 1(2020 年 4 月 25 日):

项目已移至github:https
://github.com/Antonio112009/Many-To-Many_with_extra_column 底部错误已解决,但出现另一个:我可以将一个对象连接到另一个对象,但无法连接相同的多个对象互相打字。问题和错误在github上进行了描述。

org.springframework.orm.jpa.JpaSystemException: Could not set field value [SHORT_CIRCUIT_INDICATOR] value by reflection : [class com.antonio112009.manyToMany.entity.PostTagId.tagId] 
setter of com.antonio112009.manyToMany.entity.PostTagId.tagId; nested exception is org.hibernate.PropertyAccessException: Could not set field value [SHORT_CIRCUIT_INDICATOR] 
value by reflection : [class com.antonio112009.manyToMany.entity.PostTagId.tagId] setter of com.antonio112009.manyToMany.entity.PostTagId.tagId

下面是我试图在我的项目中实现的代码:

产品.java:

@Entity
@Data
@Table
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "product_generator")
    @SequenceGenerator(name="product_generator", sequenceName = "seq_product", allocationSize = 1)
    private Long id;

    @Column
    private String name;

    @OneToMany(
            mappedBy = "product",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    List<DishSize> dishSizes = new ArrayList<>();

    public void addDishSize(DishSize dishSize) {
        dishSizes.add(dishSize);
        dishSize.setProduct(this);
    }

    public void removeDishSize(DishSize dishSize) {
        dishSizes.remove(dishSize);
        dishSize.setProduct(null);
    }
}

DishSize.java

@Entity
@Data
@Table
public class DishSize implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    private Integer size;

    @ManyToOne(fetch = FetchType.LAZY)
    private Product product;

    @ManyToOne(fetch = FetchType.LAZY)
    private Dish dish;
}

菜.java

@Entity
@Data
@Table
public class Dish {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "dish_generator")
    @SequenceGenerator(name="dish_generator", sequenceName = "seq_dish", allocationSize = 1)
    private Long id;

    @Column
    private String name;

    @OneToMany(
            mappedBy = "dish",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    List<DishSize> dishSizes = new ArrayList<>();

    public void addDishSize(DishSize dishSize) {
        dishSizes.add(dishSize);
        dishSize.setDish(this);
    }

    public void removeDishSize(DishSize dishSize) {
        dishSizes.remove(dishSize);
        dishSize.setDish(null);
    }

测试我的程序是否失败:

DishRepositoryTest.java

@SpringBootTest
class DishRepositoryTest {

    @Autowired
    private DishRepository dishRepository;

    @Autowired
    private ProductRepository productRepository;

    private String name = "Цезарь";

    @BeforeEach
      void setUp() {
        productRepository.deleteAll();
        dishRepository.deleteAll();

        Dish dish = new Dish();
        dish.setName(name);
        dish.setNotes("тест");
        dishRepository.save(dish);
    }

    @Test
    @Transactional
    void deleteProductButNotDish(){

        String nameProduct = "яблоко";
        Integer size = 250;

        Product product = new Product();
        product.setName(nameProduct);
        productRepository.save(product);
        product = productRepository.findByNameAndSort(nameProduct, null);
        Dish dish = dishRepository.findByName(name);

        DishSize dishSize = new DishSize();
        dishSize.setDish(dish);
        dishSize.setSize(size);

        product.addDishSize(dishSize);
        dish.addDishSize(dishSize);
        dishRepository.save(dish);

        //Test
        product = productRepository.findByNameAndSort(nameProduct, null);
        product.getDishSizes().get(0).getDish().removeDishSize(product.getDishSizes().get(0));
        productRepository.save(product);
        productRepository.deleteByNameAndSort(nameProduct, null);

        dish = dishRepository.findByName(name);

        assertNotNull(dish, "checking if dish is not deleted");
        assertNull(productRepository.findByNameAndSort(nameProduct, null), "checking if product is deleted");
        assertEquals(0, dish.getDishSizes().size(), "checking if dishSize is deleted");
    }
}
java
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Antonio112009
    2020-05-04T05:29:28Z2020-05-04T05:29:28Z

    Github 上的示例

    @ManyToMany c дополнительной колонкой可以在这里找到一个工作示例

    当前,删除其中嵌套了一个或多个对象的对象存在问题。

    更新 1

    删除多个对象的问题几乎解决了。剩下的就是添加对象的级联删除。

    主要要求:

    1. 不要使用@Data 龙目岛。问题出在@EqualsAndHashCode. 可以在此问题中找到有关此事物的来源的链接
    2. equals, addTag/Post,removeTag/Post的写法应与以下示例相同。没有它们,就不可能连接两个实体。

    正确的代码输入

    菜.java

    @Entity
    @Getter
    @Setter
    @Table
    public class Dish{
    
        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "dish_generator")
        @SequenceGenerator(name="dish_generator", sequenceName = "seq_dish", allocationSize = 1)
        private Long id;
    
        @Column
        private String name;
    
        @OneToMany(
                mappedBy = "dish",
                cascade = CascadeType.ALL,
                orphanRemoval = true
        )
        List<DishSize> dishSizes = new ArrayList<>();
    
        public void addProduct(Product product, Integer size) {
            DishSize dishSize = new DishSize(product,this,size);
            dishSizes.add(dishSize);
            product.getDishSizes().add(dishSize);
        }
    
        public void removeProduct(Product product) {
            for (Iterator<DishSize> iterator = dishSizes.iterator(); iterator.hasNext(); ) {
                DishSize dishSize = iterator.next();
    
                if (dishSize.getDish().equals(this) &&
                        dishSize.getProduct().equals(product)) {
                    iterator.remove();
                    dishSize.getProduct().getDishSizes().remove(dishSize);
                    dishSize.setProduct(null);
                    dishSize.setDish(null);
                }
            }
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
    
            Dish other = (Dish) obj;
            return id != null && id.equals(other.getId());
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(name);
        }
    }
    

    DishSize.java

    @Entity
    @Getter
    @Setter
    @Table
    public class DishSize {
    
        @EmbeddedId
        private DishSizePK id;
    
        @Column
        private Integer size;
    
        @ManyToOne(fetch = FetchType.LAZY)
        @MapsId("productId")
        private Product product;
    
        @ManyToOne(fetch = FetchType.LAZY)
        @MapsId("dishId")
        private Dish dish;
    
        public DishSize() {}
    
        public DishSize(Product product, Dish dish, Integer size) {
            this.product = product;
            this.dish = dish;
            this.id = new DishSizePK(product.getId(), dish.getId());
            this.size = size;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
    
            if (o == null || getClass() != o.getClass())
                return false;
    
            DishSize that = (DishSize) o;
            return Objects.equals(product, that.product) &&
                    Objects.equals(dish, that.dish);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(product, dish);
        }
    }
    

    DishSizePK.java

    @Embeddable
    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    public class DishSizePK implements Serializable {
    
        @Column
        private Long productId;
    
        @Column
        private Long dishId;
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
    
            if (o == null || getClass() != o.getClass())
                return false;
    
            DishSizePK that = (DishSizePK) o;
            return Objects.equals(productId, that.productId) &&
                    Objects.equals(dishId, that.dishId);
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(productId, dishId);
        }
    }
    

    产品

    @Entity
    @Getter
    @Setter
    @ToString
    @Table
    public class Product{
    
        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "product_generator")
        @SequenceGenerator(name="product_generator", sequenceName = "seq_product", allocationSize = 1)
        private Long id;
    
        @Column
        private String name;
    
        @OneToMany(
                mappedBy = "product",
                cascade = CascadeType.ALL,
                orphanRemoval = true
        )
        List<DishSize> dishSizes = new ArrayList<>();
    
        public void addDish(Dish dish, Integer size) {
            DishSize dishSize = new DishSize(this,dish,size);
            dishSizes.add(dishSize);
            dish.getDishSizes().add(dishSize);
        }
    
        public void removeDish(Dish dish) {
            for (Iterator<DishSize> iterator = dishSizes.iterator(); iterator.hasNext(); ) {
                DishSize dishSize = iterator.next();
    
                if (dishSize.getProduct().equals(this) &&
                        dishSize.getDish().equals(dish)) {
                    iterator.remove();
                    dishSize.getDish().getDishSizes().remove(dishSize);
                    dishSize.setProduct(null);
                    dishSize.setDish(null);
                }
            }
        }
    
        @Override
        public boolean equals(Object obj) {
    
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
    
            Product other = (Product) obj;
            return id != null && id.equals(other.getId());
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(name);
        }
    }
    
    • 0

相关问题

  • wpcap 找不到指定的模块

  • 如何以编程方式从桌面应用程序打开 HTML 页面?

  • Android Studio 中的 R.java 文件在哪里?

  • HashMap 初始化

  • 如何使用 lambda 表达式通过增加与原点的距离来对点进行排序?

  • 最大化窗口时如何调整元素大小?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5