• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Hibernate - relacja wiele do wielu

Object Storage Arubacloud
0 głosów
1,207 wizyt
pytanie zadane 11 czerwca 2019 w Java przez JuniorPL Użytkownik (770 p.)

Cześć, mam pewien problem z stworzeniem relacji wiele do wielu. Stworzyłem dwie tabele główne między którymi ma występować ta relacja oraz tabelę spinającą. Stworzyłem również oba modele tych klas które mapuję. Problem polega na tym że po dodaniu obiektów do bazy danych w tabeli łączącej nie ma żadnych danych.

Modele reprezentujące obie tabele.

Klasa User

@Entity
@Table(name="users", schema = "carassistant")
public class User {

	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id_user")
	private int id;
	
	
	@Column(name="last_name")
	private String lastName;
	
	@Column(name="first_name")
	private String firstName;

	@Column(name="email")
	private String email;
	
	@Column(name="enabled")
	private byte enabled;
	
	
	@ManyToMany(fetch=FetchType.LAZY,
			cascade= {CascadeType.PERSIST, CascadeType.MERGE,
			 CascadeType.DETACH, CascadeType.REFRESH})
	@JoinTable
	(
	name="u_users_authorites",
	joinColumns=@JoinColumn(name="id_user"),
	inverseJoinColumns=@JoinColumn(name="id_authorites_table")
	)	
	private List<Authorities> authorites;
		
	
	public User( String lastName, String firstName, String email, int i) {

		//this.id = id;
		this.lastName = lastName;
		this.firstName = firstName;
		this.email = email;
		this.enabled = (byte) i;
	}
		
	public User()
	{}
		
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public byte getEnabled() {
		return enabled;
	}
	public void setEnabled(byte enabled) {
		this.enabled = enabled;
	}
	
	
}

Klasa Authorities

@Entity
@Table(name="authorities", schema = "carassistant")
public class Authorities {
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id_authorities")
	private int id;
	
	@Column(name="password")
	private String password;
	
	@Column(name="username")
	private String username;
	
	@ManyToMany(fetch=FetchType.LAZY,
			cascade= {CascadeType.PERSIST, CascadeType.MERGE,
			 CascadeType.DETACH, CascadeType.REFRESH})
	@JoinTable(
			name="u_users_authorites",
			joinColumns=@JoinColumn(name="id_authorities"),
			inverseJoinColumns=@JoinColumn(name="id_user_table"))
	private List<User> user;
	

	public Authorities(String password, String username) 
	{		
		
		this.password = password;
		this.username = username;
	}
	

	public Authorities()
	{}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}

	
	
}

Dwa interfejsy do pracy z klasą:


public interface AuthoritiesRepository extends JpaRepository<Authorities, Integer> 
{

	public List<Authorities> findAll();
	
}

AuthoritiesService:


public interface AuthoritiesService
{

	   List<Authorities> findAll();
		
	   Authorities findById(int id);
	     
	   void save(Authorities authorities);
		
	   void deleteByIdCarType(int Authorities);
		
}

Oraz jego implementacja:


@Service
public class AuthoritiesServiceImpl implements AuthoritiesService{

	
private AuthoritiesRepository authoritiesRepository;
	
	@Autowired
	public AuthoritiesServiceImpl(AuthoritiesRepository authoritiesRepository) 
	{
		this.authoritiesRepository = authoritiesRepository;
	}
	
	@Override
	public List<Authorities> findAll() 
	{	
		return authoritiesRepository.findAll();
	}

	@Override
	public Authorities findById(int idCarType) 
	{
        
		Optional<Authorities> result = authoritiesRepository.findById(idCarType);
		
		Authorities authorities = null;
		
		if (result.isPresent()) {
			authorities = result.get();
		}
		else {
		
			throw new RuntimeException("Did not find car type id - " + idCarType);
		}		
		return authorities;
	}
	
	@Override
	public void save(Authorities authorities) 
	{
		authoritiesRepository.save(authorities);	
	}

	@Override
	public void deleteByIdCarType(int idCarType)
	{
		
		authoritiesRepository.deleteById(idCarType);
		
	}

	
}

Może ktoś podpowie gdzie popełniam błąd. Dla klasy User interfejsy i ich implementacja jest podobna więc nie zamieszczam jej. Z góry dzięki za pomoc.

1 odpowiedź

0 głosów
odpowiedź 11 czerwca 2019 przez Aisekai Nałogowiec (42,190 p.)
wybrane 12 czerwca 2019 przez JuniorPL
 
Najlepsza
O ile mi wiadomo, to jeżeli tworzysz relacje ManyToMany w dwie strony (bidirectional) to jedna z tych adnotacji, poainna mieć "ustawiony" atrybut mappedBy. W dodatku, jeżeli używasz inverseJoinColumn i joinColumn, to pierwsza wartość z pierwszej @Entity powinna odpowiadać drugiej wartości z drugiej @Entity i na odwrót. Te dwie adnotacje są odpowiedzialne za klucze główne i obce.

Tutaj przykład mappedBy @ManyToMany : https://www.baeldung.com/hibernate-many-to-many

Ps: czy repozytoria nie powinny być oznaczone @Repository (albo chociaż @Component)?
komentarz 11 czerwca 2019 przez JuniorPL Użytkownik (770 p.)

Poprawiłem fragment o którym mówiłeś

	@ManyToMany(mappedBy="authorites")
	private List<User> user;

Ale mam jeszcze problem z poprawnym działaniem. Problem może być w miejscu zapisywania do bazy.

ArrayList<User> listaUser = new ArrayList<User>();
	ArrayList<Authorities> listaAuthorities = new ArrayList<Authorities>();
	User user = new User("lastName","firstName","email@marek",1);	
	Authorities authorites = new Authorities("test123","marek");
		

                        listaUser.add(user);
			listaAuthorities.add(authorites);
			user.setAuthorites(listaAuthorities);
			authorites.setUser(listaUser);
			
		authoritiesService.save(authorites);
		userService.save(user);

Nie wiem czy dobrze to zrozumiałem.

komentarz 11 czerwca 2019 przez Aisekai Nałogowiec (42,190 p.)

Co znaczy?

problem z poprawnym działaniem

 

komentarz 11 czerwca 2019 przez JuniorPL Użytkownik (770 p.)
Tabela pośrednia jest pusta.
komentarz 11 czerwca 2019 przez Aisekai Nałogowiec (42,190 p.)
komentarz 11 czerwca 2019 przez JuniorPL Użytkownik (770 p.)
Narobiłem troche fementu z tym że aplikacja dodaje do dwóch tabel tylko nie do tabeli spinającej. Prawdopodobnie problem jest tu:

Stack tracer:

Caused by: java.sql.SQLSyntaxErrorException: Unknown column 'id_user' in 'field list'

W podczas zapisywania obiektu user do bazy pojawia się ten błąd.
komentarz 11 czerwca 2019 przez Aisekai Nałogowiec (42,190 p.)

A jaki leci sql leci do bazy podczas tworzenia tabel? Czy w bazie danych, masz dla usera pole "id" czy "id_user"? Problem prawdopodobnie leży w Hibernetowym NamingStrategy: https://github.com/spring-projects/spring-boot/issues/2129 

Spróbowałbym też zmienić typ int na Integer, albo Long - może coś pomoże. 

Podobne pytania

+1 głos
1 odpowiedź 538 wizyt
pytanie zadane 12 lipca 2021 w Java przez kozluck Nowicjusz (220 p.)
0 głosów
0 odpowiedzi 209 wizyt
0 głosów
2 odpowiedzi 1,493 wizyt

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...