# Spring Data JPA ### 1. pom.xml 設定 > 加入spring-boot-starter-data-jpa依賴 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> ``` ### 2. 建立Model * @Entity的Bean是告訴Spring這是數據模型層的宣告 * @Table name: Table的name對映到資料庫中的資料表名稱 * @Column name: 對應到Table的欄位中的欄位名稱 * @Id : 是此資料表的Primary Key * @GeneratedValue : 告訴此Column的生成方式 ,如果設定成GenerationType.AUTO讓容器來自動產生 > <font color='red'>需對應資料庫裡的course_student資料表</font> > 可以省略@Table,但是要確保資料庫內有與此Model類別一樣名稱的資料表 ```java= package eyes.media.student.vo; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.Table; @Entity @Table(name = "course_student") @IdClass(CourseStudentId.class) public class CourseStudent { @Id private String courseid; @Id private String studentid; private String gradelevel; public String getCourseid() { return courseid; } public void setCourseid(String courseid) { this.courseid = courseid; } public String getStudentid() { return studentid; } public void setStudentid(String studentid) { this.studentid = studentid; } public String getGradelevel() { return gradelevel; } public void setGradelevel(String gradelevel) { this.gradelevel = gradelevel; } @Override public String toString() { return "CourseStudent [courseid=" + courseid + ", studentid=" + studentid + ", gradelevel=" + gradelevel + "]"; } } ``` ### 3-1. 組合鍵設定方式 Composite Primary Keys >須遵循下列規則 > * The composite primary key class must be public > * It must have a no-arg constructor > * It must define equals() and hashCode() methods > * It must be Serializable ```java= package eyes.media.student.vo; import java.io.Serializable; import javax.persistence.Id; public class CourseStudentId implements Serializable { /** * */ private static final long serialVersionUID = 1L; @Id private String courseid; @Id private String studentid; public CourseStudentId() { } public CourseStudentId(String courseid, String studentid) { this.courseid = courseid; this.studentid = studentid; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((courseid == null) ? 0 : courseid.hashCode()); result = prime * result + ((studentid == null) ? 0 : studentid.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; CourseStudentId other = (CourseStudentId) obj; if (courseid == null) { if (other.courseid != null) return false; } else if (!courseid.equals(other.courseid)) return false; if (studentid == null) { if (other.studentid != null) return false; } else if (!studentid.equals(other.studentid)) return false; return true; } } ``` ### 3-2. 組合鍵設定方式 Composite Primary Keys ```java= @Entity public class YourEntity { @EmbeddedId private MyKey myKey; @Column(name = "ColumnA") private String columnA; /** Your getters and setters **/ } ``` ```java= @Embeddable public class MyKey implements Serializable { @Column(name = "Id", nullable = false) private int id; @Column(name = "Version", nullable = false) private int version; /** getters and setters **/ } ``` ### 3-2. UUID主鍵設定方式 ```java= @Id @GeneratedValue(generator = "uuidGenerator") @GenericGenerator(name = "uuidGenerator", strategy = "uuid") @Column(length = 32) private String workId; ``` ### 4. 建立Interface > 建立一個繼承 CrudRepository 的介面: > CrudRepository 這個介面,定義了 save、findById、delete 等方法,繼承的時候,只要指定對應表格的類型與 id 類型,剩下的就交給 Spring Data JDBC 來處理了。 ### 5. 客製化SQL語法 > 可以使用 @Query 與 @Modifying 來定義,@Query 中可以撰寫 SQL,相關的參數可以使用 @Param 來標註對應,如果是個更新操作,額外標註 @Modifying 就可以了。 > 非HQL原生語法需加上 <font color='red'>**nativeQuery = true**</font> ```java= package eyes.media.student.dao; import java.util.List; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import eyes.media.student.vo.CourseStudent; @Repository public interface CourseStudentDao extends CrudRepository<CourseStudent, String> { @Query(value = "SELECT * FROM course_student cs WHERE cs.courseid = :courseid", nativeQuery = true) List<CourseStudent> findCouresStuByCourseId(@Param("courseid") String courseid); } ``` ### 6. 回傳結果處裡 ```java= //You will get null when Student not found public Student getStudent(String studentId) { return studentRepository.findById(studentId).orElse(null); } public Student getStudent(String studentId) { return studentRepository.findById(studentId).get(); } public List<Student> findAll() { List<Student> students = new ArrayList<>(); studentRepository.findAll().forEach(students::add); return students; } //insert @Transactional public void add(Student vo) { studentDao.save(vo); } ``` 資料來源: [Day12-Spring Boot-什麼是Spring Data JPA](https://ithelp.ithome.com.tw/articles/10194906) [Composite Primary Keys in JPA](https://www.baeldung.com/jpa-composite-primary-keys) [簡介 Spring Data JDBC](https://openhome.cc/Gossip/Spring/SpringDataJDBC.html) [Spring Boot中CrudRepository与JpaRepository](https://blog.csdn.net/xuemengrui12/article/details/80525227) [理解JPA注解@GeneratedValue](https://blog.csdn.net/canot/article/details/51455967) ###### tags: `Spring boot` `Spring Data JPA`