【问题标题】:Allow duplicate values in MySQL using Spring boot使用 Spring Boot 允许 MySQL 中的重复值
【发布时间】:2021-07-07 15:59:04
【问题描述】:

我在互联网上搜索了我的问题,但没有找到任何有用的东西(或者至少我没有很好地搜索????‍♂️) 问题是:我打算让不同的猫有相同的玩具关系(cat_id 可以有不同 cat_id 的相同 toy_id) 不允许在数据库中使用我的代码重复。 添加了 MySQL 工作台屏幕截图以适应问题。 (对不起我的英语不好)

我正在使用 JPA 来完成这项任务。 我做错了什么?

mysql workbench screenshot

猫类

@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "cats")
public class Cat {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private float weight;
    private String color;

    @OneToMany(cascade = CascadeType.ALL)
    @Singular
    private List<Toy> toys;
}

玩具抽象类

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name = "toys")

public abstract class Toy {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected int id;

    protected String name;
}

特定玩具类

@Entity
public class Ball extends Toy {
    public Ball() {
        super();
        name = "Ball";
    }
}

测试类

@Component
@RequiredArgsConstructor
@Order(1)
public class TestCatService implements CommandLineRunner {

    private final CatService service;

    @Override
    public void run(String... args) throws Exception {
        Toy t1 = new Ball();
        Toy t2 = new RubberBand();
        Toy t3 = new Mouse();
        Toy t4 = new Ball();

        //////////////////////////////////////////////////////////////////////
        TestUtils.printTestInfo("Add Pink Cat");
        Cat pinkCat = Cat.builder().color("Pink")
                .name("Mitzi")
                .weight(4.3f)
                .toy(t1)
                .toy(t3)
                .build();
        try {
            service.addCat(pinkCat);
            System.out.println("Cat added to DB");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        //////////////////////////////////////////////////////////////////////
        TestUtils.printTestInfo("Add White Cat");
        Cat whiteCat = Cat.builder()
                .color("White")
                .name("Mitzi")
                .weight(4.3f)
                .toy(t1)
                .toy(t2)
                .toy(t3)
                .build();
        try {
            service.addCat(whiteCat);
            System.out.println("Cat added to DB");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        //////////////////////////////////////////////////////////////////////

        TestUtils.printTestInfo("Add tricolor Cat");
        Cat tricolorCat = Cat.builder()
                .color("Tri-color")
                .name("shocki")
                .weight(2.7f)
                .build();
        try {
            service.addCat(tricolorCat);
            System.out.println("Cat added to DB");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        
        TestUtils.printTestInfo("Add Orange Cat");
        Cat orange = Cat.builder()
                .color("Orange")
                .name("jinji")
                .toy(t3)
                .toy(t4)
                .weight(6.2f)
                .build();
        try {
            service.addCat(orange);
            System.out.println("Cat added to DB");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        
        //////////////////////////////////////////////////////////////////////
        TestUtils.printTestInfo("Update Cat to Pink Color");
        whiteCat.setColor("Pink");
        try {
            service.updateCat(whiteCat);
            System.out.println("Cat updated");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        //////////////////////////////////////////////////////////////////////
        TestUtils.printTestInfo("Update Cat to Black Color");
        whiteCat.setColor("Black");
        try {
            service.updateCat(whiteCat);
            System.out.println("Cat updated");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        
    }

}

控制台输出

_______________________________________
         Testing "Add Pink Cat"                  
Pink cats are not allowed
_______________________________________
         Testing "Add White Cat"                  
Cat added to DB
_______________________________________
         Testing "Add tricolor Cat"                  
Cat added to DB
_______________________________________
         Testing "Add Orange Cat"                  
detached entity passed to persist: com.jb.lab4.beans.toys.Toy; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.jb.lab4.beans.toys.Toy
_______________________________________
         Testing "Update Cat to Pink Color"                  
Pink cats are not allowed
_______________________________________
         Testing "Update Cat to Black Color"                  
Cat updated

更新

只有当我使用 toyRepository.saveAll(t1, t2. t3) 将玩具显式添加到数据库并删除 @ManyToMany 注释中的级联选项时,我才设法使代码按预期工作。

代码如下

@Component
@RequiredArgsConstructor
@Order(1)
public class TestCatService implements CommandLineRunner {

    private final CatService service;
    private final ToyRepository toyRepository;

    @Override
    public void run(String... args) throws Exception {
        Toy t1 = new Ball();
        Toy t2 = new RubberBand();
        Toy t3 = new Mouse();
        Toy t4 = new Ball();
        
        // manually add toys to database
        toyRepository.saveAll(Arrays.asList(t1,t2,t3,t4));

        //////////////////////////////////////////////////////////////////////
        TestUtils.printTestInfo("Add Pink Cat");
        Cat pinkCat = Cat.builder().color("Pink")
                .name("Mitzi")
                .weight(4.3f)
                .toy(t1)
                .toy(t3)
                .build();
        try {
            service.addCat(pinkCat);
            System.out.println("Cat added to DB");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        //////////////////////////////////////////////////////////////////////
        TestUtils.printTestInfo("Add White Cat");
        Cat whiteCat = Cat.builder()
                .color("White")
                .name("Mitzi")
                .weight(4.3f)
                .toy(t1)
                .toy(t2)
                .toy(t3)
                .build();
        try {
            service.addCat(whiteCat);
            System.out.println("Cat added to DB");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        //////////////////////////////////////////////////////////////////////

        TestUtils.printTestInfo("Add tricolor Cat");
        Cat tricolorCat = Cat.builder()
                .color("Tri-color")
                .name("shocki")
                .weight(2.7f)
                .build();
        try {
            service.addCat(tricolorCat);
            System.out.println("Cat added to DB");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        TestUtils.printTestInfo("Add Orange Cat");
        Cat orange = Cat.builder()
                .color("Orange")
                .name("jinji")
                .toy(t1)
                .toy(t4)
                .weight(6.2f)
                .build();
        try {
            service.addCat(orange);
            System.out.println("Cat added to DB");
        } catch (Exception e) {
            System.out.println(e.getMessage());

        }

        //////////////////////////////////////////////////////////////////////
        TestUtils.printTestInfo("Update Cat to Pink Color");
        whiteCat.setColor("Pink");
        try {
            service.updateCat(whiteCat);
            System.out.println("Cat updated");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        //////////////////////////////////////////////////////////////////////
        TestUtils.printTestInfo("Update Cat to Black Color");
        whiteCat.setColor("Black");
        try {
            service.updateCat(whiteCat);
            System.out.println("Cat updated");
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

    }

}
@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "cats")
@Primary
public class Cat {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String name;
    private float weight;
    private String color;

    // removed the @ManyToMany(cascade = CascadeType.ALL) option
    @ManyToMany
    @Singular
    private List<Toy> toys;
}

现在有了这个变化,多只猫可以像预期的那样拥有多个玩具。

如果我放回 @ManyToMany(cascade = CascadeType.ALL) 代码会中断并出现异常 org.hibernate.PersistentObjectException: detached entity pass to persist。

我的目的不是手动保存玩具,我希望将它们与猫豆一起添加到数据库中。

任何想法为什么它不适用于级联?

【问题讨论】:

  • 你想要多对多的关系,对吧?
  • @code_mechanic 如果我做对了。我还尝试用@ManyToMany 替换@OneToMany 注释,但得到相同的结果,不允许重复
  • 只放注解可能行不通,要多对多工作,您需要从双方定义关系,请检查此how
  • @code_mechanic 谢谢你的链接????????,我去看看

标签: java mysql spring spring-boot jpa


【解决方案1】:
public class Cat {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @OneToMany(cascade = CascadeType.ALL)
    @Singular
    private List<Toy> toys;

仔细检查。 @OneToMany 这里的意思是 1 只猫可以拥有很多玩具。但是@OneToMany 与另一侧的另一个注释一起出现,即使您不使用它并使其单向。该注释是@ManyToOne。 所以如果你有双向的话。

 public class Toy {
    @ManyToOne
    private Cat cat;
 }

这意味着多个玩具仅与 1 只猫有关。你看我要去哪里。这种关系不允许同一个玩具出现在多只猫中。 1 只猫是许多玩具!

所以你想要的解决方案是@ManyToMany

 public class Cat {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int id;
    
        @ManyToMany(cascade = CascadeType.ALL)
        @Singular
        private List<Toy> toys;

这里的意思是多只猫有多个玩具,而且在另一边即使你不使用它也会是

public class Toy {
        @ManyToMany
        private List<Cat> cat;
     }

这也意味着多个玩具有多个猫。

现在这允许单个玩具与 2 只或更多猫进行映射。

【讨论】:

  • 如果我放回@ManyToMany(cascade = CascadeType.ALL) 代码中断并出现异常org.hibernate.PersistentObjectException: detached entity passed to persist 我的意图不是手动保存玩具,我希望将它们与猫豆一起添加到数据库中。有什么想法为什么它不适用于级联?
  • 用你用来保存的代码更新你的问题
  • 你想和玩具一起拯救的猫在哪里?
【解决方案2】:

你可以像这样使用一对多的关系。

@OneToMany(mappedBy = "cats",
            cascade = {CascadeType.REMOVE})
private List<Toy> toys;

在玩具课上,你可以这样做。

@ManyToOne(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinColumn(name = "cats_id", nullable = true)
    private Cat cat;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 2019-04-22
    • 2018-03-14
    • 2019-12-16
    • 2017-09-15
    • 2015-07-22
    相关资源
    最近更新 更多