Skip to content

Spring Data JPA 实践 ​

实验目标 ​

使用 Spring Data JPA 构建数据访问层,掌握 JPA 关系映射和查询。

实验 1:配置数据库 ​

application.properties:

properties
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

实验 2:定义实体 ​

java
@Entity
@Table(name = "authors")
public class Author {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false)
    private String name;
    
    @Column(unique = true)
    private String email;
    
    @OneToMany(mappedBy = "author", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Book> books = new ArrayList<>();
    
    public void addBook(Book book) {
        books.add(book);
        book.setAuthor(this);
    }
    
    // getters and setters
}

@Entity
@Table(name = "books")
public class Book {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(nullable = false)
    private String title;
    
    @Column(length = 13)
    private String isbn;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "author_id")
    private Author author;
    
    // getters and setters
}

实验 3:Repository 接口 ​

java
public interface AuthorRepository extends JpaRepository<Author, Long> {
    Optional<Author> findByEmail(String email);
    List<Author> findByNameContainingIgnoreCase(String name);
}

public interface BookRepository extends JpaRepository<Book, Long> {
    
    List<Book> findByTitleContaining(String title);
    
    List<Book> findByAuthor_Id(Long authorId);
    
    @Query("SELECT b FROM Book b WHERE b.author.name = :authorName")
    List<Book> findByAuthorName(@Param("authorName") String authorName);
    
    @Query(value = "SELECT * FROM books WHERE isbn = ?1", nativeQuery = true)
    Optional<Book> findByIsbn(String isbn);
}

实验 4:Service 层 ​

java
@Service
@Transactional
public class LibraryService {
    
    @Autowired
    private AuthorRepository authorRepository;
    
    @Autowired
    private BookRepository bookRepository;
    
    public Author createAuthorWithBooks(String authorName, List<String> bookTitles) {
        Author author = new Author();
        author.setName(authorName);
        
        for (String title : bookTitles) {
            Book book = new Book();
            book.setTitle(title);
            author.addBook(book);
        }
        
        return authorRepository.save(author);
    }
    
    public void transferBook(Long bookId, Long newAuthorId) {
        Book book = bookRepository.findById(bookId)
            .orElseThrow(() -> new ResourceNotFoundException("Book not found"));
        
        Author newAuthor = authorRepository.findById(newAuthorId)
            .orElseThrow(() -> new ResourceNotFoundException("Author not found"));
        
        book.setAuthor(newAuthor);
        bookRepository.save(book);
    }
}

实验 5:测试完整流程 ​

java
@SpringBootTest
class LibraryServiceTest {
    
    @Autowired
    private LibraryService libraryService;
    
    @Test
    void testCreateAuthorWithBooks() {
        Author author = libraryService.createAuthorWithBooks(
            "J.K. Rowling",
            Arrays.asList("Harry Potter 1", "Harry Potter 2")
        );
        
        assertNotNull(author.getId());
        assertEquals(2, author.getBooks().size());
    }
    
    @Test
    @Transactional
    void testTransferBook() {
        // 创建两个作者
        Author author1 = new Author();
        author1.setName("Author 1");
        
        Author author2 = new Author();
        author2.setName("Author 2");
        
        // 创建书籍
        Book book = new Book();
        book.setTitle("Test Book");
        author1.addBook(book);
        
        authorRepository.save(author1);
        authorRepository.save(author2);
        
        // 转移书籍
        libraryService.transferBook(book.getId(), author2.getId());
        
        // 验证
        Book updatedBook = bookRepository.findById(book.getId()).get();
        assertEquals(author2.getId(), updatedBook.getAuthor().getId());
    }
}

验收标准 ​

✅ 实体正确映射到数据库表
✅ 关系映射正常工作
✅ Repository 查询方法正确
✅ 事务管理正常
✅ 测试通过

返回第三章概览

用心记录每一步成长