@EntitypublicclassBook{@Id@GeneratedValue(strategy=GenerationType.IDENTITY)privateLongid;@Column(nullable=false)privateStringtitle;privateStringauthor;privateintyear;protectedBook(){}// required by JPApublicBook(Stringtitle,Stringauthor,intyear){…}// getters, and setters only where they make sense}
Warning
Entities are mutable objects tied to a persistence context — not DTOs. Records cannot be
entities. Map to a record before returning data from a controller.
You write no implementation — Spring Data derives the query from the method name.
Inherited for free: save, saveAll, findById, findAll, delete, count,
findAll(Pageable).
Own queries
@Query("select b from Book b where b.year between :from and :to")List<Book>inRange(intfrom,intto);@Query(value="select * from book order by random() limit 1",nativeQuery=true)Bookrandom();
Controllers can take a Pageable parameter directly: ?page=1&size=20&sort=title,asc.
Transactions
@ServicepublicclassBookService{privatefinalBookRepositoryrepo;BookService(BookRepositoryrepo){this.repo=repo;}@TransactionalpublicBookrename(longid,Stringtitle){varbook=repo.findById(id).orElseThrow(()->newBookNotFoundException(id));book.setTitle(title);// dirty checking writes on commitreturnbook;}@Transactional(readOnly=true)publicList<Book>all(){returnrepo.findAll();}}
Rules: @Transactional belongs on the service, rolls back on unchecked exceptions, and only
works when the call comes in from outside the bean (it is a proxy).
Schema management
Setting
Use
spring.jpa.hibernate.ddl-auto=create-drop
tests, demos
…=update
local development, never production
…=validate
production, with Flyway or Liquibase for migrations