You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring JPA:含List属性的Movie实体数据库设计与save方法使用

Spring JPA Movie-Genre Design & Save() Usage

Hey there! Let's tackle your questions about designing your movie database with Spring JPA and using the save() method effectively. I'll walk through each question with explanations and practical code examples.


1. Should I create separate Movie and Genre tables with a relationship?

Absolutely—this is the standard, database-normalized approach for handling many-to-many relationships (a movie can have multiple genres, and a genre can belong to multiple movies). Here's why it's the right choice:

  • Maintains data consistency (no duplicate genre strings scattered across movie entries)
  • Enables efficient, targeted queries (e.g., "find all movies in the 'Action' genre")
  • Makes updating genre names trivial (no need to edit every movie that uses the genre)

Example Entity Classes

First, create the Genre entity to represent distinct genre records:

package com.kurshit.moviesmgr.vo;

import jakarta.persistence.*;
import java.util.List;

@Entity
@Table(name = "genres")
public class Genre {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(unique = true, nullable = false)
    private String name;
    
    @ManyToMany(mappedBy = "genres")
    private List<Movie> movies;

    // Constructors, getters, setters
    public Genre() {}
    
    public Genre(String name) {
        this.name = name;
    }

    // Getters and setters omitted for brevity
}

Then update the Movie entity to define the many-to-many relationship:

package com.kurshit.moviesmgr.vo;

import jakarta.persistence.*;
import java.util.List;

@Entity
@Table(name = "movies")
public class Movie {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long movieId;
    
    @Column(nullable = false)
    private String title;
    
    @Column(name = "year_of_release")
    private String yearOfRelease;
    
    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(
        name = "movie_genre",
        joinColumns = @JoinColumn(name = "movie_id"),
        inverseJoinColumns = @JoinColumn(name = "genre_id")
    )
    private List<Genre> genres;

    // Constructors, getters, setters
    public Movie() {}
    
    public Movie(String title, String yearOfRelease, List<Genre> genres) {
        this.title = title;
        this.yearOfRelease = yearOfRelease;
        this.genres = genres;
    }

    // Getters and setters omitted for brevity
}

2. Can I store all genres as CSV in a single column?

Technically yes, but this is strongly discouraged for most production use cases. Here's the tradeoff:

Pros

  • Simpler table structure (only one movies table)

Cons

  • No efficient way to query by genre (you'd have to use slow, error-prone LIKE queries)
  • Duplicate genre data across movies (e.g., "Action" stored hundreds of times)
  • Updating a genre name requires editing every movie entry that uses it

If you still need this approach (e.g., for a small, low-traffic app), you can use a JPA converter to map the List<String> to a CSV string:

package com.kurshit.moviesmgr.converters;

import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Converter(autoApply = true)
public class GenreListConverter implements AttributeConverter<List<String>, String> {
    private static final String SEPARATOR = ",";

    @Override
    public String convertToDatabaseColumn(List<String> genres) {
        return genres != null ? String.join(SEPARATOR, genres) : null;
    }

    @Override
    public List<String> convertToEntityAttribute(String dbData) {
        return dbData != null ? Arrays.stream(dbData.split(SEPARATOR)).collect(Collectors.toList()) : List.of();
    }
}

Then update your Movie entity to use this converter:

@Entity
@Table(name = "movies")
public class Movie {
    // ... other fields ...
    
    @Column(name = "genres")
    @Convert(converter = GenreListConverter.class)
    private List<String> genres;

    // ... constructors, getters, setters ...
}

3. Can I use the repository's save() method directly?

Yes! Once your entities are properly annotated (either for the normalized many-to-many setup or the CSV converter approach), Spring JPA's JpaRepository will handle all mapping and storage logic automatically.

Example Repository Interface

package com.kurshit.moviesmgr.repositories;

import com.kurshit.moviesmgr.vo.Movie;
import org.springframework.data.jpa.repository.JpaRepository;

public interface MovieRepository extends JpaRepository<Movie, Long> {
    // Add custom query methods here if needed, e.g.:
    // List<Movie> findByGenresName(String genreName);
}

Usage Example

// In a service or controller class
@Autowired
private MovieRepository movieRepository;

public void saveSampleMovies() {
    // For the normalized many-to-many approach:
    Genre action = new Genre("Action");
    Genre comedy = new Genre("Comedy");
    Movie avengers = new Movie("The Avengers", "2012", List.of(action, comedy));
    movieRepository.save(avengers);

    // For the CSV approach:
    Movie deadpool = new Movie("Deadpool", "2016", List.of("Action", "Comedy"));
    movieRepository.save(deadpool);
}

内容的提问来源于stack exchange,提问作者Kurshit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:20:25