[Spring] JPA Annotations Overview
- Hibernate/JPA CRUD (3)
 - Hibernate 는 그냥 spring boot 디폴트 JPA implementation 이다?
 
JPA Dev Process - To do list
- Annotate Java Class
 - Develop Java Code to perform database operations
 
Let’s just say “JPA”
- As mentioned, Hibernate is the default JPA implementation in SpringBoot
 - Going forward in this course, I will simply use the term:JPA
    
- Instead of saying “JPA Hibernate”
 
 - We know that by default, Hibernate is used behind the scenes
 
Terminology
- Entity Class
    
- Java class that is mapped to a database table
 
 
Object-to-Relational Mapping(ORM)

Entity Class
- At a minimum, the Entity class
    
- Must be annotated with @Entity
 - Must have a public or protected no-argument constructor
        
- The class can have other constructors
 
 
 
Constructors in Java - Refresher
- Remember about constructors in Java
 - If you don’t declare any constructors
    
- Java will provide a no-argument constructor for free
 
 - If you declare constructors with arguments
    
- then you do NOT get a no-argument constructor for free
 - In this case, you have to explicitly declare a no-argument constructor
 
 
Java Annotations
- Step 1: Map class to database table
 - Step 2: Map fields to database columns
 
Step 1: Map class to database table
@Entity
@Table(name="student")
public class Student {
...
}

Step 2: Map fields to database columns
@Entity
@Table(name="student")
public class Student {
	@id
	@Column(name="id")
	private int id;
	@Column(name="first_name")
	private String firstName;
}

@Column - Optional
- Actually, the use of @Column is optional
 - If not specified, the column name is the same name as Java field
 - In general, I don’t recommend this approach
    
- If you refactor the Java code, then it will not match existing database columns
 - This is a breaking change and you will need to update database column
 
 - Same applies to @Table database table name is same as the class
 
Terminology
- Primary Key
    
- Uniquely identifies each row in a table
 - Must be a unique value
 - Cannot contain NULL values
 
 
MySQL - Auto Increment
CREATE TABLE student (
	id int NOT NULL AUTO_INCREMENT,
	first_name varchar(45) DEFAULT NULL,
	last_name varchar(45) DEFAULT NULL,
	email varchar(45) DEFAULT NULL,
	PRIMARY KEY (id)
)
JPA Identity - Primary Key
@Entity
@Table(name="student")
public class Student {
	@id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="id")
	private int id;
	...
}
ID Generation Strategies
| Name | Description | 
|---|---|
| GenerationType.AUTO | Pick an appropriate strategy for the particular database | 
| GenerationType.IDENTITY | Assign primary keys using database identity column (Recommend) | 
| GenerationType.SEQUENCE | Assign primary keys using a database sequence | 
| GenerationType.TABLE | Assign primary keys using an underlying database table to ensure uniqueness | 
근데 프로젝트에서 특정한 id를 사용해야되고 제약이 많고 뭐 그럴 경우에는 어떡하지?
- If at my company, on our project, nothing that JPA provides out of the box matches our requirement.
    
- You can define your own CUSTOM generation strategy
 - Create implementation of org.hibernate.id.IdentifierGenerator
 - Override the method: public Serializable generate(…)
 
 
데이터 연결작업
MySQL 과 연결하기
File : src/main/resources/application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/student_tracker  
spring.datasource.username=springstudent  
spring.datasource.password=springstudent
@SpringBootApplication  
public class CruddemoApplication {  
  
   public static void main(String[] args) {  
      SpringApplication.run(CruddemoApplication.class, args);  
   }  
  
   @Bean  
   public CommandLineRunner commandLineRunner(String[] args){  
      return runner-> {  
         System.out.println("Hello World");  
      };  
   }  
}
@Entity, @Table 로 데이터 연결
@Entity  
@Table(name="student")  
public class Student {  
  
    // define fields  
    @Id  
    @GeneratedValue(strategy = GenerationType.IDENTITY)  
    @Column(name = "id")  
    private int id;  
  
    @Column(name = "first_name")  
    private String firstName;  
  
    @Column(name = "last_name")  
    private String lastName;  
  
    @Column(name = "email")  
    private String email;  
  
  
    // define constructors  
    public Student(){  
  
    }  
  
    public Student(String firstName, String lastName, String email) {  
        this.firstName = firstName;  
        this.lastName = lastName;  
        this.email = email;  
    }  
  
    // define getters/setters  
  
    public int getId() {  
        return id;  
    }  
  
    public void setId(int id) {  
        this.id = id;  
    }  
  
    public String getFirstName() {  
        return firstName;  
    }  
  
    public void setFirstName(String firstName) {  
        this.firstName = firstName;  
    }  
  
    public String getLastName() {  
        return lastName;  
    }  
  
    public void setLastName(String lastName) {  
        this.lastName = lastName;  
    }  
  
    public String getEmail() {  
        return email;  
    }  
  
    public void setEmail(String email) {  
        this.email = email;  
    }  
  
  
    // define toString() method  
  
    @Override  
    public String toString() {  
        return "Student{" +  
                "id=" + id +  
                ", firstName='" + firstName + '\'' +  
                ", lastName='" + lastName + '\'' +  
                ", email='" + email + '\'' +  
                '}';  
    }  
}  
- Lombok을 사용하면 코드를 더욱 축소 시킬 수 있다.
 - 하지만 롤백에 시간이 오래 걸리고 모든 사람이 롬복 프러그인이 필요하고 기타 등등 단점도 분명 존재한다.
 - 또한 Lombok 사용시 모든 계층이 Lombok에 의존하게 되므로 버그 발생시 분리된 모듈이 아닌 전체 어플리케이션에 걸쳐 나타날 수 있다고 한다.
    
- Python이 아닌 Java를 쓰는 이유가 사라지는 느낌이라 굳이 써야되나 싶다.
 
 
출처 : 유데미, luv2code.com, https://velog.io/@kay019/Lombok%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC-%ED%95%A0%EA%B9%8C
댓글남기기