Jpa ManyToMany关系不起作用

时间:2019-04-23 16:21:27

标签: mysql spring-boot jpa

我有SpringBoot 2.1.3 + MySql 5.7数据库。我正在尝试在2个实体之间建立ManyToMany关系:

@Entity
@Data
public class User {
    private String name;
    @ManyToMany(cascade = CascadeType.ALL)
    private List<Hobby> hobbies;
}

@Entity
@Data
public class Hobby {
    private String description;
    @ManyToMany(mappedBy = "hobbies")
    private List<User> users;
}

现在是否要进行测试:

User user = new User();
user.setName("James");
user.setHobbies(new ArrayList<>());

Hobby hobby = new Hobby();
hobby.setDescription("Golf");
hobby.setUsers(new ArrayList<>());

user.getHobbies.add(hobby);
hobby.getUsers.add(user);

userRepository.save(user);

所有三个表(用户表,Hobby表和jpa创建的映射之一)都将持久保存,如下所示:

USER              USER_HOBBY               HOBBY
id, name          iduser, idhobby          id, description
1   James         1        1               1   Golf

但如果现在我打电话

List<User> us = userRepository.findAll();

我们内部我没有任何爱好实体。它说:

com.sun.jdi.InvocationException occurred invoking method.

我的具有数据库配置的application.properties:

# Connection url for the database "test"
spring.datasource.url = jdbc:mysql://localhost:3306/test?useSSL=false

# ===============================
# = JPA / HIBERNATE
# ===============================

spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true

我已按照Google找到的所有示例尝试了所有方法。 怎么了?

谢谢

2 个答案:

答案 0 :(得分:0)

我认为您在致电userRepository.findAll()之前不会保存爱好实体。

如果在实体之间创建关系,则需要在保存和搜索全局实体之前保存所有实体从属。

如果在依赖项字段中保存带NULL的实体,则它们不会引发异常。在您的情况下,您保存了一个空列表,但是休眠状态无法保存,因为他的支票FK并没有找到这个爱好。

您可以尝试使用NULL或数据库爱好中存在的用户进行保存。像这样:

List<Hobby> hobbies = hobbyRepository.findAll();

user.getHobbies().addAll(hobbies); // null pointer exception
userRepository.save(user);

userRepository.findAll();

我不明白为什么您的存储库允许您保存。我使用postgres,并且接口在JpaRepository上扩展,如果我用空的兴趣爱好列表保存用户,它们会抛出异常。


我尝试过:

Hobby h = new Hobby();
h.setDesc("Golf");
hobbyRepository.save(h);

List<Hobby> hobbies = hobbyRepository.findAll();

Persona p = new Persona();
p.setNome("Giacomo");
p.setHobbies(new ArrayList<>());
p.getHobbies().addAll(hobbies);
personaRepository.save(p);

List<Persona> persone = personaRepository.findAll();
List<Hobby> hobby = hobbyRepository.findAll();

不工作。.你能做一个与此示例类似的工作示例吗?我将不胜感激,因为我不明白错误在哪里。 附言如果我放:

@ManyToMany(fetch = FetchType.EAGER)

它有效..但是我不想放它!!它应该使用默认值。

答案 1 :(得分:0)

已解决。这是一个Session问题,有不同的解决方案。

首先是添加访存注释:

@Entity
@Data
public class User {
  private String name;
  @ManyToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
  private List<Hobby> hobbies;
}

这样,每次您找到用户实体时,您都将获取所有相关的兴趣爱好。其他解决方案(更好)是保留默认的访存值(对于许多关系是惰性的),并在用于检索数据的方法上添加 @Transactional 注释。

@Transactional
public void searchData() {
  User user = new User();
  user.setName("James");
  user.setHobbies(new ArrayList<>());

  Hobby hobby = new Hobby();
  hobby.setDescription("Golf");
  hobby.setUsers(new ArrayList<>());

  user.getHobbies.add(hobby);
  hobby.getUsers.add(user);

  userRepository.save(user);

  List<User> us = userRepository.findAll();
  for (User u : us) {
    System.out.println(u.getHobbies().size()); // print 1
  }
}

希望有帮助。