(Long)id | (String)memberName |
---|---|
1 | mallang |
2 | quokka |
(Long)id | (String)foodName | (int)price |
---|---|---|
1 | ๋งค์ด๊ฐ๋น์ฐ | 30,000 |
2 | ๋ง๊ณ ๋น์ | 10,000 |
โ Member ํ ์ด๋ธ์ ์ฃผ๋ฌธ์ ๋ณด ๋ฃ์ผ๋ฉด โ Member ๋ฐ์ดํฐ ์ค๋ณต ๐จ
โก Food ํ ์ด๋ธ์ ์ฃผ๋ฌธ์ ๋ณด ๋ฃ์ผ๋ฉด โ Food ๋ฐ์ดํฐ ์ค๋ณต ๐จ
โข Orders๋ง์ ๋ค๋ฃจ๋ ํ ์ด๋ธ ์ถ๊ฐ โ๏ธ
(Long)id | Member_id | Food_id | Time |
---|---|---|---|
1 | 1 | 1 | 2023.07.24 22:00 |
2 | 1 | 2 | 2023.07.24 23:00 |
๐ JPA์ฐ๊ด๊ด๊ณ
: Entity ํด๋์ค ํ๋ ์ โ ์ฐ๊ด๊ด๊ณ Annotation ์ค์ โ ํ์ฑ์๋ฃ
์ฐ๊ด๊ด๊ณ | Annotation | Entity | content |
---|---|---|---|
1 : N (์ผ๋๋ค) | @OneToMany | Orders(1) : Food(N) | ๋ฐฐ๋ฌ์ฃผ๋ฌธ 1๊ฐ์ N๊ฐ ์์ ์ ํ๊ฐ๋ฅ |
N : 1 (๋ค๋์ผ) | @ManyToOne | Owner(N) : Restaurant(1) | ์ฌ์ฅ N๋ช ์ด 1๊ฐ์ ์์์ ์์ ๊ฐ๋ฅ |
1 : 1 (์ผ๋์ผ) | @OneToOne | Orders(1) : Coupon(1) | ๋ฐฐ๋ฌ์ฃผ๋ฌธ 1๊ฑด์ ์ฟ ํฐ 1๊ฐ๋ง ์ ์ฉ๊ฐ๋ฅ |
N : M (๋ค๋๋ค) | @ManyToMany | Member(N) : Restaurant(M) | ๊ณ ๊ฐ์ ์์์ ์ฌ๋ฌ๊ฐ ์ฐ๊ธฐ๋ฅ, ์์์ ์ ๊ณ ๊ฐ ์ฌ๋ฌ๋ช ์๊ฒ ์ฐ๊ธฐ๋ฅ |
๊ตฌ๋ถ | ์ญํ |
---|---|
Group | ๊ธฐ์
์ ๋๋ฉ์ธ ๋ช
(๋ค๋ถํฐ ์์ผ๋ก ์) ๊ฐ์ธํ๋ก์ ํธ โ ์์ ๋กญ๊ฒ ์ค์ ๊ฐ๋ฅ |
Artifact | ๋น๋๋ ๊ฒฐ๊ณผ๋ฌผ์ ์ด๋ฆ |
Package Name | ํจํค์ง๋ช |
Packaging | [๋ฐฐํฌํํ] โ jar - Java ์ดํ๋ฆฌ์ผ์ด์ ์ด ๋์ํ ์ ์๊ฒ ํ๋ก์ ํธ๋ฅผ ์์ถํ ํ์ผ - class + ๋ผ์ด๋ธ๋ฌ๋ฆฌํ์ผ - JRE๋ง ์์ด๋ ์คํ๊ฐ๋ฅ โก war - Servlet, Jsp ์ปจํ ์ด๋๋ฅผ ๋ฐฐ์นํ ์ ์๋ ์น์ดํ๋ฆฌ์ผ์ด์ ์ ์์ถํ ํ์ผ - ์นํ๋ก์ ํธ โ jsp, html, javascript ํฌํจ - ์น์๋ฒ๋ was๊ฐ ํ์ํจ โก๏ธ ์นํ๋ฉด์ด ํ์ํ ์ดํ๋ฆฌ์ผ์ด์ ์ war๋ก ํจํค์ง, api ์๋ฒ์ฌ์ฉ์ ํ๋ก์ ํธ๋ก๋ง ๋์ํ๋ฉด ๋๊ธฐ๋๋ฌธ์ jar๋ก ํจํค์ง |
Java, SpringBoot ๋ฒ์ | - โ SpringBoot 3.XX โ Java 17 ์ด์ ์ฌ์ฉ - โก SpringBoot 2.XX โ Java 11 ์ฌ์ฉ โก๏ธ SNAPSHOT, M1์ ์ ์๋ฒ์ โ |
Entity, Repository ๋๋ ํ ๋ฆฌ ์์ฑ
1๊ฐ์ Entity โ 1๊ฐ์ Repository
.gitignore
โ ๋ฏผ๊ฐ์ ๋ณด ๋ณดํธ๋ฅผ ์ํด src/
ํ์ํ์ผ๋ง pushํจ
@Getter
@Entity
@NoArgsConstructor // class ๋ชจ๋ ํ๋ -> ๊ธฐ๋ณธ์์ฑ์ ์๋์ถ๊ฐ
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // PK์์ฑ -> DB์ ์์์ ๋ต
private Long id;
@Column(nullable = false)
private String memberName;
// JPA ์ฐ๊ด๊ด๊ณ์ค์
// ์ผ๋๋ค -> ์ฐ๊ด๊ด๊ณ์ฃผ์ธ : member, ์ฆ์๋ก๋ฉ EAGER์ฌ์ฉ
// ์ฆ์๋ก๋ฉ : member + order(์ฐ๊ด๊ด๊ณํ
์ด๋ธ) ํจ๊ป์กฐํ
// ์ง์ฐ๋ก๋ฉ : member๋ง ์กฐํ, ์ฐ๊ด๊ด๊ณํ
์ด๋ธ ์กฐํ๋ ๋ฏธ๋ฃธ
@OneToMany(mappedBy = "member", fetch = FetchType.EAGER)
private List<Orders> orders = new ArrayList<>();
// ์์ฑ์
public Member(String memberName) {
this.memberName = memberName;
}
}
@Getter
@Entity
@NoArgsConstructor
public class Food {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String foodName;
@Column(nullable = false)
private int price;
// JPA ์ฐ๊ด๊ด๊ณ์ค์
@OneToMany(mappedBy = "food", fetch = FetchType.EAGER)
private List<Orders> orders = new ArrayList<>();
public Food(String foodName, int price) {
this.foodName = foodName;
this.price = price;
}
}
@Getter
@Entity
@NoArgsConstructor // class ๋ชจ๋ ํ๋ -> ๊ธฐ๋ณธ์์ฑ์ ์๋์ถ๊ฐ
public class Orders {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // PK์์ฑ -> DB์ ์์์ ๋ต
private Long id;
// JPA ์ฐ๊ด๊ด๊ณ์ค์
// ๋ค๋์ผ -> ์ฐ๊ด๊ด๊ณ์ฃผ์ธ : member, Member Entity PK๋ก ์ฐ๊ฒฐ
@ManyToOne
@JoinColumn(name = "member_id")
private Member member;
@ManyToOne
@JoinColumn(name = "food_id")
private Food food;
// ์์ฑ์
public Orders(Member member, Food food) {
this.member = member;
this.food = food;
}
}
public interface MemberRepository extends JpaRepository<Member, Long> {
}
// ์ธํฐํ์ด์ค ์์ฑ -> JpaRepository<Entityํด๋์ค, PKํ์
> ์์์ํด
// ๊ธฐ๋ณธ์ ์ธ CRUD ๋ฉ์๋๊ฐ ์๋์ผ๋ก ์์ฑ๋จ
public interface FoodRepository extends JpaRepository<Food, Long> {
}
public interface OrdersRepository extends JpaRepository<Orders, Long> {
}
# H2 ์ฐ๊ฒฐ
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:db
spring.datasource.username=mallang
spring.datasource.password=
username์ ๋ณธ์ธ ์ฌ๋์ ๋ง๊ฒ ์ค์ ๊ฐ๋ฅ
build.gradle
> dependencies
โ runtimeOnly 'com.h2database:h2'
์ค์ ๋์ด์๋์ง ํ์ธ
โ IntelliJ RUN
โก ํฌ๋กฌ > localhost:8080/h2-console
์ ์
@Component // ๊ฐ๋ฐ์ ์์ฑ class -> SpringBean ๋ฑ๋ก
@RequiredArgsConstructor // final, @Notnull ํ๋ -> ์์ฑ์ ์๋์ผ๋ก ๋ง๋ค์ด์ค
public class Restaurant implements ApplicationRunner {
private final MemberRepository memberRepository;
private final FoodRepository foodRepository;
private final OrdersRepository ordersRepository;
@Override
public void run(ApplicationArguments arguments) throws Exception {
List<Food> foods = new ArrayList<>();
Food food1 = new Food("ํ๋ผ์ด๋", 10000);
foods.add(food1);
Food food2 = new Food("์๋
์นํจ", 12000);
foods.add(food2);
Food food3 = new Food("๋ฐ๋ฐ์นํจ", 13000);
foods.add(food3);
Food food4 = new Food("๊ณ ๊ตฌ๋งํผ์", 9000);
foods.add(food4);
Food food5 = new Food("์๋ณด์นด๋ํผ์", 110000);
foods.add(food5);
foodRepository.saveAll(foods);
System.out.println("==================================================================");
// FoodRepository -> ๊ฐ์ฒด๋ฅผ ์ ๋ถ ์ฝ์ด์ด -> ๋ฐ๋ณต๋ฌธ์ ํตํด FoodName๋ง get
List<Food> findFoods = foodRepository.findAll();
for (Food findFood : findFoods) {
System.out.println("findFood = " + findFood.getFoodName());
}
List<Member> members = new ArrayList<>();
Member member1 = new Member("๋ง๋์ด");
members.add(member1);
Member member2 = new Member("์ฟผ์นด");
members.add(member2);
memberRepository.saveAll(members);
System.out.println("==================================================================");
// MemberRepository -> ๊ฐ์ฒด๋ฅผ ์ ๋ถ ์ฝ์ด์ด -> ๋ฐ๋ณต๋ฌธ์ ํตํด MemberName๋ง get
System.out.println("Member ๋ฐ์ดํฐ");
List<Member> findMembers = memberRepository.findAll();
for (Member findMember : findMembers) {
System.out.println("findMember = " + findMember.getMemberName());
}
List<Orders> ordersList = new ArrayList<>();
// Java List -> ์์๋ณด์ฅ๋จ -> Entity ์์์ ๋ง์ถฐ ์ด๊ธฐ๊ฐ ๋ฃ์ด์ฃผ๊ธฐ
Orders orders1 = new Orders(findMembers.get(0), findFoods.get(0));
ordersList.add(orders1);
Orders orders2 = new Orders(findMembers.get(1), findFoods.get(3));
ordersList.add(orders2);
Orders orders3 = new Orders(findMembers.get(1), findFoods.get(4));
ordersList.add(orders3);
Orders orders4 = new Orders(findMembers.get(0), findFoods.get(2));
ordersList.add(orders4);
Orders orders5 = new Orders(findMembers.get(0), findFoods.get(2));
ordersList.add(orders5);
Orders orders6 = new Orders(findMembers.get(1), findFoods.get(1));
ordersList.add(orders6);
Orders orders7 = new Orders(findMembers.get(0), findFoods.get(1));
ordersList.add(orders7);
Orders orders8 = new Orders(findMembers.get(1), findFoods.get(3));
ordersList.add(orders8);
ordersRepository.saveAll(ordersList);
System.out.println("==================================================================");
int num = 1;
System.out.println("Orders ๋ฐ์ดํฐ");
List<Orders> orderList = ordersRepository.findAll();
for (Orders orders : orderList) {
System.out.println(num);
System.out.println("์ฃผ๋ฌธ์ = " + orders.getMember().getMemberName());
System.out.println("์ฃผ๋ฌธ์์ = " + orders.getFood().getFoodName());
num++;
}
System.out.println("==================================================================");
System.out.println("๋ง๋์ด๊ฐ ์ฃผ๋ฌธํ ์์");
Member mallang = memberRepository.findById(1L).orElseThrow(
() -> new RuntimeException("์์")
);
num = 1;
for (Orders orders : mallang.getOrders()) {
System.out.println(num);
System.out.println("์ฃผ๋ฌธ์์ = " + orders.getFood().getFoodName());
System.out.println("์ฃผ๋ฌธ์์๊ฐ๊ฒฉ = " + orders.getFood().getPrice());
num++;
}
System.out.println("==================================================================");
System.out.println("์๋ณด์นด๋ํผ์ ์ฃผ๋ฌธ์");
Food abocado = foodRepository.findById(5L).orElseThrow(
() -> new RuntimeException("์์")
);
for (Orders orders : abocado.getOrders()) {
System.out.println("์ฃผ๋ฌธ์ = " + orders.getMember().getMemberName());
}
}
}
@Getter
// ๊ณตํต Mapping ์ ๋ณด๊ฐ ์กด์ฌํ ๋ ์ฌ์ฉ
// ๋ถ๋ชจํด๋์ค๋ฅผ ์์๋ฐ๋ ์์ํด๋์ค์๊ฒ ๋งตํ์ ๋ณด๋ง ์ ๊ณตํ๊ณ ์ถ์ ๋
// Entity๋ Entity๋ง ์์๋ฐ์ ์ ์๊ธฐ๋๋ฌธ์, ํด๋์ค๋ฅผ Entity์ ์์์ํค๊ธฐ์ํ ๋ฐฉ๋ฒ
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class Timestamped {
// ์์ฑ์๊ฐ
@CreatedDate
// Entity ์์ ์, ํด๋น ํ๋ ์์ ์ ๋ง์ -> ์ฝ๊ธฐ์ ์ฉ
@Column(updatable = false)
private LocalDateTime createdAt;
// ์์ ์๊ฐ
@LastModifiedDate
@Column(updatable = true) // ๊ธฐ๋ณธ๊ฐ์ด๋ผ ์๋ต๊ฐ๋ฅ
private LocalDateTime modifiedAt;
}
public class Orders extends Timestamped {โขโขโข}
@EnableJpaAuditing // Timestamped ํด๋์ค์ฌ์ฉ์ ์ํ ์ด๋
ธํ
์ด์
@SpringBootApplication
public class FoodDeliveryApplication {โขโขโข}
๐ GitHub ๋ฐ๋ก๊ฐ๊ธฐ
๐ Spring Data JPA
: JPA๋ฅผ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ๊ธฐ์ํด Spring์์ Wrappingํ ๊ฒ
JPA ์ฌ์ฉ ์, ํ์์ ์ด์ง๋ง ์์๊ฐ๋ฅํ๊ณ ๋ฐ๋ณต์ ์ธ ์ฝ๋ โ Spring Data JPA๊ฐ ๋์ ์์ฑ
Repository์ interface๋ง ์์ฑ โ ํ์ํ ๊ตฌํ์ Spring์ด ๋์ ํจ