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 查询方法正确
✅ 事务管理正常
✅ 测试通过
返回第三章概览