본문 바로가기

수업 복습하기/Spring

Day 05 - Spring04 + TimeMapper -> mapper.xml/.java

728x90
728x90

= p05controller =

- /cont09/met10 -

< TimeMapper.java >

package org.zerock.mapper.p05mapper;

import java.util.List;

import org.apache.ibatis.annotations.Select;
import org.zerock.controller.p05controller.bean.Bean09;
import org.zerock.controller.p05controller.bean.Bean10;

public interface TimeMapper {

@Select("SELECT customerName, contactName FROM Customers WHERE CustomerID = 1")
	public Bean10 getName();
    }

< Controller09.java >

	package org.zerock.controller.p05controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.zerock.controller.p05controller.bean.Bean09;
import org.zerock.controller.p05controller.bean.Bean10;
import org.zerock.mapper.p05mapper.TimeMapper;

import lombok.Setter;

@Controller
@RequestMapping("/cont09")
public class Controller09 {
    
    @RequestMapping("/met10")
	public void method10() {
		Bean10 name = mapper.getName();
		System.out.println(name); 
		// 1번 고객의 CustomerName, ContactName이 출력되도록 코드 작성
	
    }
}

< Bean10.java >

package org.zerock.controller.p05controller.bean;

import lombok.Data;

@Data
public class Bean10 {
//customerName, contactName
	private String customerName;
	private String contactName;
}

대소문자 구분이 없다는 것을 알아야 한다고 사실 이름을 이상하게 바꾸어봤지만, 그냥 정상적인 형태로 돌렸다.


- /cont09/met11 -

< TimeMapper.java >

 

	@Select("SELECT customerID AS id, customerName FROM Customers WHERE CustomerID = 1")
	public Bean11 getCustomerInfo();

< Controller09.java >

 

	@RequestMapping("/met11")
	public void method11() {
		System.out.println(mapper.getCustomerInfo());
	}

< Bean11.java >

 

package org.zerock.controller.p05controller.bean;

import lombok.Data;

@Data
public class Bean11 {
	private Integer id;
	private String customerName;
}

쿼리에 별칭을 주는 방법 as쓰기! 

실제 테이블이 가지고있는 테이블 column명과 bean이 가지고있는 property가 다르더라도 result값에 의해서 잘 들어간 것을 확인 할 수 있다.


- /cont09/met12-

< TimeMapper.java >

 

	@Select("SELECT customerID AS id, customerName FROM Customers WHERE CustomerID = 1")
	public Bean11 getCustomerInfo();

< Controller09.java >

	@RequestMapping("/met12")
	public void method12() {
		System.out.println(mapper.getEmployeeInfo());
	}
	//id, last name, first name 넣어보기

< Bean12.java >

package org.zerock.controller.p05controller.bean;

import lombok.Data;

@Data
public class Bean12 {
	private Integer id;
	private String lname; //last name
	private String fname; //first name
}

As 활용하기 exercise.

/AS가 빠지고 이름 바로 들어가도 되니까 그거 까먹지 말기 (엄청 자주 까먹는다)


- /cont09/met13-

< TimeMapper.java >

	@Select("SELECT EmployeeID, LastName, FirstName, BirthDate, Photo, Notes FROM Employees WHERE EmployeeID = #{id}")
	public Bean13 getEmployeeById(Integer id);

< Controller09.java >

 

	@RequestMapping("/met13")
	public void method13(Integer id) {
		System.out.println(mapper.getEmployeeById(id));
	}

< Bean13.java >

 

package org.zerock.controller.p05controller.bean;

import java.time.LocalDate;

import lombok.Data;

@Data
public class Bean13 {
	
	private Integer employeeID; 
	private String lastName;
	private String firstName;
	private String photo;
	private String notes;
	private LocalDate birthDate;
}

/id 번호 입력해서 내가 원하는 번호 입력했을 때, 그 정보 가져오기 연습! localdate로 날짜도 잘 갖고 오는지확인하기

 

 


- /cont09/met14-

< TimeMapper.java >

	@Select("SELECT CustomerID, CustomerName, ContactName,"
			+ " City, Address, Country, PostalCode "
			+ "FROM Customers "
			+ "WHERE CustomerID = #{id}")
	public Bean14 getCustomerById(Integer id);

< Controller09.java >

 

	@RequestMapping("/met14")
	public void method14(Integer id) {
		// TODO: mapper에 getCustomerById 메소드 (Bean14 리턴) 만들기
		//      Bean14빈의 property가 Customers 테이블의 컬럼과 매치되도록 작성
		System.out.println(mapper.getCustomerById(id));
	}

< Bean14.java >

 

package org.zerock.controller.p05controller.bean;

import lombok.Data;

@Data
public class Bean14 {
	private Integer customerID;
	private String customerName;
	private String contactName;
	private String city;
	private String address;
	private String postalCode;
	private String country;
}

/controller에 작성된걸 보고 나머지 내가 만들어보기 exercise

timemapper, bean을 작성해보자 (mysql에 desc customers;) 해본 다음 필요한 열 찾아서 넣으면 된다.


- /cont09/met15 -

< TimeMapper.java >

	@Select("SELECT CustomerID, customerName, ContactName, "
			+ "City, Address, Country, PostalCode "
			+ "FROM Customers")
	public List<Bean14> getCustomers();

< Controller09.java >

	@RequestMapping("/met15")
	private void method15() {
		List<Bean14> list = mapper.getCustomers();
		for(Bean14 item : list) {
			System.out.println(item);
		}
	}

< Bean14.java >

package org.zerock.controller.p05controller.bean;

import lombok.Data;

@Data
public class Bean14 {
	private Integer customerID;
	private String customerName;
	private String contactName;
	private String city;
	private String address;
	private String postalCode;
	private String country;
}

/이제 리스트에 bean아이템들을 담아서 하는 것 까지 연습해보자.

controller만들 때, for을 사용해서 list를 작성했다. 간만에 향상된 for문이군! 출력 잘되는 것 확인 완료


- /cont09/met16 -

< TimeMapper.java >

	@Select("SELECT EmployeeID, LastName, FirstName, BirthDate, Photo, Notes FROM Employees" )
	public List<Bean13> getEmployees();

< Controller09.java >

	@RequestMapping("/met16")
	public void method16() {
		List<Bean13> list = mapper.getEmployees();
		
		for (Bean13 item : list) {
			System.out.println(item);
		}
	}

< Bean13.java >

package org.zerock.controller.p05controller.bean;
import java.time.LocalDate;
import lombok.Data;

@Data
public class Bean13 {
	private Integer employeeID; 
	private String lastName;
	private String firstName;
	private String photo;
	private String notes;
	private LocalDate birthDate;
}

/ met16직접 만들어보기! timemapper만 수정하면 완료가능~


- /cont09/met17 -

TimeMapper.java >

	@Select("SELECT p.ProductName, c.CategoryName, p.Unit, p.Price " + 
			"FROM Products p JOIN Categories c ON p.CategoryID = c.CategoryID")
	public List<Bean15> getProductsInfo();

Controller09.java >

	@RequestMapping("/met17")
	private void method17() {
		List<Bean15> list = mapper.getProductsInfo();
		for(Bean15 item : list) {
			System.out.println(item);
		}
	}

Bean15.java >

package org.zerock.controller.p05controller.bean;

import lombok.Data;

@Data
public class Bean15 {
	private String productName;
	private String categoryName;
	private String unit;
	private Double price;
}

- /cont09/met18 -

TimeMapper.java >

	public List<Bean15> getProductsInfo2();

Controller09.java >

 

	@RequestMapping("/met18")
	public void method18() {
		List<Bean15> list = mapper.getProductsInfo2();
		
		for (Bean15 item : list) {
			System.out.println(item);
		}
	}

Bean15.java >

package org.zerock.controller.p05controller.bean;

import lombok.Data;

@Data
public class Bean15 {
	private String productName;
	private String categoryName;
	private String unit;
	private Double price;
	
}

/3가지 직접 처음부터 끝까지 다 만들어보기 !

활용할 식은 

"SELECT p.ProductName, c.CategoryName, p.Unit, p.Price FROM Products p JOIN Categories c ON p.CategoryID = c.CategoryID"

desc products

desc categories

로 어떠한 타입인지 확인한 후에, 작성하기

세개 다 작성해보면서 헷갈리는 부분이 없었는지확인하면 좋을 것 같다


/ xml 타임메퍼 만들기 /

어노테이션보다 더 자주 사용하는 형태

new - file - TimeMapper.xml 확장자가 xml인 것 확인하기!

여러줄을 잘표현할 수있으니까, 마이바티스로 사용한거 갖고와야하니까 설정하기~

mybatis 사이트접속 (참고하기)

https://mybatis.org/mybatis-3/ko/getting-started.html

매핑된 sql 구문 살펴보기 파트에서 

코드식 제일 위의 4줄을 복사해서 TimeMapper.xml 제일 위에다가 붙여넣었음!

그리고 mapper 안에 select를 넣고 mapper에다가 namespace를 붙여넣는데,

실제 timemapper젤 위에 위치 복사해서 붙여넣기해서 식을 완성했다.

셀렉트 쿼리가 어느 메소드와 관련이 있는지 select id에 메소드 이름을 적어주면 된다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.zerock.mapper.p05mapper.TimeMapper">
	<!-- namespace 속성 : 인터페이스명 -->
	<select id="getProductsInfo2"
		resultType="org.zerock.controller.p05controller.bean.Bean15">
		<!-- id 속성 : 메소드명 -->
		<!-- resultType 속성 : 컬럼이 매핑될 빈 이름 -->
		SELECT
		p.ProductName, c.CategoryName, p.Unit, p.Price
		FROM
		Products p
		JOIN
		Categories c ON p.CategoryID = c.CategoryID
	</select>
</mapper>

/controller10

우리는 연습중이라 메퍼로 만들고 뭐뭐 Dao 라고 만드는게 관습인데,

우리는 번호를 붙여서 했지만 이제는 ~Mapper로 한다!는거 알고있게하기

mapper01.xml / mapper01.java

하나는 xml, 하나는 인터페이스인거 헷갈리지 말기

타임메퍼 복사해서 mapper01에 붙여넣기~ 기본적인 설정이 같아야 하니까!

mapper namespace 뒤에는 수정해야하는거 까먹지말기~

 

추가적인 수업 설명 :

간단한 구문에서는 어노테이션이 좀더 깔끔하다. 어쨌든 자바 어노테이션은 좀더 복잡한 구문에서는 제한적이고 코드를 엉망으로 만들 수 있다. 그러므로 복잡하게 사용하고자 한다면 XML 매핑 구문을 사용하는 것이 좀더 나을 것이다.

대부분 sql은 간단한 구문이 아니니까, xml을 할것이다. 하지만 우리가 배우는 식은 아직 어려운 식은 아니라 어노테이션까지는 커버가 가능하다.

 

패키지명도 풀네임으로 가져와야하는데, 그부분을 실수해서 이상한 주소를 가져오지 않게 조심해야한다.

Mapper01.java getSupplierOne() = Mapper01.xml의 select id

Mapper01.java Bean16 = Mapper01.xml resultType 주소

인터페이스 Mapper01 = mapper01.xml namespace의 주소

 

이렇게 되면서 실제로 작성해야되는 코딩 식은 총 4군데가 되었다

Controller10 / Mapper01.xml / Mapper01.java(interface) / Bean16.java

< Controller10.java  >

package org.zerock.controller.p05controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.zerock.controller.p05controller.bean.Bean09;
import org.zerock.controller.p05controller.bean.Bean16;
import org.zerock.mapper.p05mapper.Mapper01;

import lombok.Setter;

@Controller
@RequestMapping("/cont10")
public class Controller10 {

	@Setter(onMethod_=@Autowired)
	private Mapper01 mapper;
	
	@RequestMapping("/met01")
	private void method01() {
		System.out.println(mapper.getSupplierOne());
	}
	
	@RequestMapping("/met02")
	public void method02() {
		// SELECT LastName, FirstName FROM Employees WHERE EmployeeID = 3
		// Mapper01.java에 getEmployeeNameOne 메소드 작성
		// 위 메소드 리턴 타입 Bean09 사용
		// Mapper01.xml 에 새 <select> 요소 작성

		// 이 메소드에서 getEmployeeNameOne 메소드 실행 결과(Bean09) 출력
		Bean09 bean = mapper.getEmployeeNameOne();
		System.out.println(bean);
	}
	
	@RequestMapping("/met03")
	private void method03() {
		List<Bean09> list = mapper.getEmployeeNameList();
		list.forEach(n -> System.out.println(n));
		
		for(Bean09 n : list) {
			System.out.println(n);
		}
	}
	
	@RequestMapping("/met04")
	public void method04() {

//		mapper.getSupplierList().forEach(s -> System.out.println(s));

		List<Bean16> list = mapper.getSupplierList();

		for (Bean16 s : list) {
			System.out.println(s);
		}
	}
	@RequestMapping("/met05")
	private void method05() {
		System.out.println(mapper.getEmployeeLastNameOne());
	}
	
	@RequestMapping("/met06")
	public void method06() {
		System.out.println(mapper.getEmployeeFirstNameOne());// 
	}
	
	@RequestMapping("/met07")
	public void method07() {
		List<String> list = mapper.getEmployeeLastNameList();
		
		for (String lname : list) {
			System.out.println(lname);
		}
	}
}

< Mapper01.xml >

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.zerock.mapper.p05mapper.Mapper01">
	<!-- namespace 속성 : 인터페이스명 -->
	<select id="getSupplierOne"
		resultType="org.zerock.controller.p05controller.bean.Bean16">
		SELECT
		SupplierName,
		ContactName
		FROM
		Suppliers
		WHERE
		SupplierID
		= 10
	</select>

	<select id="getEmployeeNameOne"
		resultType="org.zerock.controller.p05controller.bean.Bean09">
		SELECT
		LastName, FirstName
		FROM
		Employees
		WHERE
		EmployeeID = 3
	</select>

	<select id="getEmployeeNameList"
		resultType="org.zerock.controller.p05controller.bean.Bean09">
		SELECT
		LastName,
		FirstName
		FROM
		Employees
	</select>

	<select id="getSupplierList"
		resultType="org.zerock.controller.p05controller.bean.Bean16">
		SELECT
		SupplierName,
		ContactName
		FROM
		Suppliers
	</select>

	<select id="getEmployeeLastNameOne" resultType="string">
		SELECT
		lastName
		FROM
		Employees
		WHERE
		EmployeeID = 1

	</select>

	<select id="getEmployeeFirstNameOne" resultType="string">
		SELECT
		firstName
		FROM
		Employees
		WHERE
		EmployeeID = 1
	</select>

	<select id="getEmployeeLastNameList"
		resultType="string">
		SELECT
		LastName
		FROM
		Employees
	</select>
</mapper>

< Mapper01.java >

package org.zerock.mapper.p05mapper;

import java.util.List;

import org.zerock.controller.p05controller.bean.Bean09;
import org.zerock.controller.p05controller.bean.Bean16;

public interface Mapper01 {
 
	public Bean16 getSupplierOne();
	
	public Bean09 getEmployeeNameOne();
	
	public List<Bean09> getEmployeeNameList();
	
	public List<Bean16> getSupplierList();
	
	public String getEmployeeLastNameOne();
	
	public String getEmployeeFirstNameOne();
	
	public List<String> getEmployeeLastNameList();
}

< Bean16 >

 

package org.zerock.controller.p05controller.bean;

import lombok.Data;

@Data
public class Bean16 {
	private String supplierName;
	private String contactName;
	
}

쿼리가 길어지면 길어질수록 어노테이션보다 xml에 작성하는게 편하다

 

/갑자기 람다식으로 문제풀려고 하니까 엄청 어색해서 당황스러웠다

list를 가져올 때, resulttype은 그냥 원래쓰던 bean 주소를 가져오면 된다.

 

/아까전에 푼 문제를 토대로 푼 문제, 이렇게 꾸준히 연습하다보면, 식짜는거 익숙해지겠징

 

/resultType="java.lang.String 은 resultType = "string"의 약칭으로 작성해도 된다.

-> mybatis -> 매퍼 설정 -> typealiases

 

 

/controller11

#{id}이용해서 푸는 문제 활용하기

빨간색 메소드이름 / 초록색 return 타입 / 핑크색 파라미터 이름

< Controller11.java >

package org.zerock.controller.p05controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.zerock.mapper.p05mapper.Mapper02;

import lombok.Setter;

@Controller
@RequestMapping("/cont11")
public class Controller11 {
	
	@Setter(onMethod_ = @Autowired)
	private Mapper02 mapper;

	@RequestMapping("/met01")
	private void method01(Integer id) {
	String name = mapper.getLastNameByID(id);
	System.out.println(name);
	}
	
	@RequestMapping("/met02")
	public void method02(Integer id) {
		String customerName = mapper.getCustomerNameById(id);
		
		System.out.println(customerName);
	}
	
	// /cont11/met03?category=condiments
	@RequestMapping("/met03")
	public void method03(String category) {
		List<String> productNames = mapper.getProductNamesByCategory(category);
		
		for (String p : productNames) {
			System.out.println(p);
		}
	}
	
	// /cont11/met04?category=Beverages&price=10 
	@RequestMapping("/met04")
	public void method04(String category, Double price) {
		List<String> productNames = mapper.getProductNamesByCategoryAndPrice(category, price);
		
		for (String p : productNames) {
			System.out.println(p);
		}
	}
	
	// /cont11/met05?city=Berlin&country=Germany
	@RequestMapping("/met05")
	public void method05(String city, String country) {
		List<String> supplierNames = mapper.getSupplierNamesByCityAndCountry(city, country);
		
		for (String s : supplierNames) {
			System.out.println(s);
		}
	}
}

< Mapper02.xml >

package org.zerock.mapper.p05mapper;

import java.util.List;

import org.apache.ibatis.annotations.Param;

public interface Mapper02 {

	String getLastNameByID(Integer id);

	String getCustomerNameById(Integer id);

	List<String> getProductNamesByCategory(String category);

	List<String> getProductNamesByCategoryAndPrice(@Param("category") String category, @Param("price") Double price);

	List<String> getSupplierNamesByCityAndCountry(@Param("city") String city, @Param("country") String country);

}

< Mapper02.java >

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.zerock.mapper.p05mapper.Mapper02">
	<select id="getLastNameByID" resultType="string">
		SELECT LastName
		FROM
		Employees
		WHERE EmployeeID=#{id}
	</select>

	<select id="getCustomerNameById" resultType="string">
		SELECT customerName
		FROM Customers
		WHERE CustomerID = #{id}
	</select>

	<select id="getProductNamesByCategory" resultType="string">
		SELECT
		p.ProductName
		FROM Products p JOIN Categories c ON p.CategoryID =
		c.CategoryID
		WHERE c.CategoryName = #{category}
	</select>

	<select id="getProductNamesByCategoryAndPrice"
		resultType="string">
	<![CDATA[      
	SELECT p.ProductName 
	FROM Products p JOIN Categories c ON p.CategoryID = c.CategoryID
	WHERE c.CategoryName = #{category} AND p.price < #{price}
	]]>
	</select>

	<select id="getSupplierNamesByCityAndCountry"
		resultType="string">
		SELECT SupplierName
		FROM Suppliers
		WHERE City = #{city} AND Country = #{country}
	</select>
</mapper>

/met04

태그 사용하는 기호가 < 와 같아서 부등호 기호와 문제가 생길 수 있다.

그래서 태그에 해당하는게아니라 일반텍스트다 라고 명시하는 방법 : <![CDATA[ 여기 넣고싶은 쿼리 ]]>

 


+)

param1, param2와 같이 category 나 price를 가져오라고 하는데

컴파일할 때 사람이아니어서, 글자 그대로 읽지 않기 때문에, 처음에는 바로 오류가 날 수 있다.

파람이라는 키워드를 넣는것도 불편한게 가끔, price와 카테고리가 바뀔수잇는데 그러면 전부 식을 수정해야하는 일이 발생해서 사용하는 방법 :

List<String> getProductNamesByCategoryAndPrice

(@Param("category") String category, @Param("price") Double price);

@Param("내가 사용하고싶은글자") 어노테이션과 같은 방법으로 사용하면 된다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.zerock.mapper.p05mapper.TimeMapper">
	<!-- namespace 속성 : 인터페이스명 -->
	<select id="getProductsInfo2"
		resultType="org.zerock.controller.p05controller.bean.Bean15">
		<!-- id 속성 : 메소드명 -->
		<!-- resultType 속성 : 컬럼이 매핑될 빈 이름 -->
		SELECT
		p.ProductName, c.CategoryName, p.Unit, p.Price
		FROM
		Products p
		JOIN
		Categories c ON p.CategoryID = c.CategoryID
	</select>
</mapper>

(추가)

src/main/resources - log4.xml 에서 3rdparty loggers 에서 아래꺼 level value="warn"으로 바꿔주면, 

서버 실행할 때마다, 만든 메소드가 전부 다 나오지 않게 된다.

(선생님한테 서버 재부팅할때마다 시간이 너무 오래걸리게 되어서 헬프치니까 알려주신 정보!)

728x90