Dev log - 67, Java Spring #3

박강산·2022년 7월 22일
0

스프링(Spring) 프레임워크

의존 관계 자동 설정

  • autowire : 스프링은 제공된 클래스의 코드를 통해 의존 관계를 자동으로 설정할 수 있음

    byName

    • 프로퍼티 이름과 동일한 Bean 객체를 설정
    • 프로퍼티의 이름 변경 시 참조하는 빈의 이름도 함께 변경해야 함

    byType

    • 프로퍼티 타입과 동일한 Bean 객체를 설정
    • 하나의 타입에 하나의 Bean 만을 정의할 때 사용
    • 동일 타입의 Bean이 두 개 이상이 존재하면 예외가 발생 (=> Qualifier 어노테이션 사용)

    constructor

    • 기본적으로 byType 과 동일
    • 생성자 아규먼트와 동일한 Bean 타입의 객체를 설정

    autodetect

    • 기본적으로 byType 과 동일
    • constructor 방식을 적용 후 byType 방식을 통해 Bean 객체를 설정
  • @autowired 어노테이션

  1. Bean 타입을 이용하여 의존하는 객체를 삽입
  2. 필드, 생성자, 메소드에 적용 가능
  3. 사용하기 위해서는 Bean 설정 파일에 <context:annotation-config /> 정의 필요
  4. @autowired(required=false) 설정 시, 속성 값이 있지 않아도 예외가 발생하지 않음

스프링 Bean 스캔

  • 클래스들 가운데 특정 어노테이션이 정의된 클래스를 자동으로 Bean으로 등록 가능

    Component : 가장 기본적인 스캔 대상 컴포넌트임을 정의

    Controller : 프레젠테이션 레이어 컴포넌트임을 정의

    Service : 서비스 레이어 컴포넌트임을 정의

    Repository : 퍼시스턴스 레이어 컴포넌트임을 정의

  • 등록 시 지정될 Bean의 이름은, 해당 클래스명의 첫 글자를 소문자로 바꾼 이름을 기본으로 사용
    ex)

	@Controller("memberController")
    @Scope("singleton") // Bean이 관리되는 범위의 타입을 설정
	public class MemberController {}

실습

  • afterPropertiesSet 제일 먼저 호출되고, destroy가 제일 마지막에 호출
  • initMethod = "attachWings", destroyMethod = "detachWings"

스프링 JDBC

  • 명령 프롬프트 창에서 jvx330 데이터베이스를 만듬

show databases;
use mysql
select host, user from user;
create user 'jvx330'@localhost identified by 'jvx330';
create database jvx330 default character set utf8;
show databases;
grant all privileges ON jvx330.* to 'jvx330'@localhost with grant option;
flush privileges;

  • 이클립스에서 jvx330 데이터베이스를 연결함

실습

*. DataSourceConfig.java

@Configuration
public class DataSourceConfig {

	@Bean(destroyMethod = "close")
	public DataSource dataSource() {
		DataSource ds = new DataSource();
		ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
		ds.setUrl("jdbc:mysql://localhost:3306/jvx330?serverTimezone=Asia/Seoul");
		ds.setUsername("jvx330");
		ds.setPassword("jvx330");
		ds.setInitialSize(2); // 커넥션 풀 초기화 시 생성할 초기 커넥션 갯수 (기본값 10)
		ds.setMaxActive(10); // 풀에서 가져올 수 있는 최대 커넥션 갯수 (기본값 100)
		ds.setMaxIdle(10); // 풀에 유지할 수 있는 최대 커넥션 수 (기본값은 maxActive와 동일)
		return ds;
	}
    
	@Bean
	public AddCustomerDataSourceDao addCustomerDataSourceDao() {
		return new AddCustomerDataSourceDao(dataSource());
	}
}

*. AddCustomerDataSourceDao.java

public class AddCustomerDataSourceDao {
	private DataSource dataSource;

	public AddCustomerDataSourceDao(DataSource dataSource) {
		this.dataSource = dataSource;
	}

	public void addCustomer(Customer customer) {
		String sql = "INSERT INTO Customer (email, passwd, name, ssn, phone) VALUES (?, ?, ?, ?, ?)";

		try (Connection con = dataSource.getConnection(); PreparedStatement pstmt = con.prepareStatement(sql);) {
			pstmt.setString(1, customer.getEmail());
			pstmt.setString(2, customer.getPasswd());
			pstmt.setString(3, customer.getName());
			pstmt.setString(4, customer.getSsn());
			pstmt.setString(5, customer.getPhone());

			pstmt.executeUpdate();
			con.close();

		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DataSourceConfig.class);
		AddCustomerDataSourceDao dao = context.getBean("addCustomerDataSourceDao", AddCustomerDataSourceDao.class);
		Customer c = new Customer();
		c.setEmail("yubi@java.com");
		c.setPasswd("1111");
		c.setName("유비");
		c.setSsn("800111-1234567");
		c.setPhone("010-5599-2285");
		dao.addCustomer(c);
		System.out.println("-Inserted-");
		context.close();
	}
}

실습2

  • 스프링에서 제공하는 JDBC 템플릿을 이용해서 간단하게 연결하는 방법

  • Config 클래스에서 JdbcTemplate을 생성하거나, 클래스 자체에서 생성하면 됨

  • addCustomer와 addCustomer2 의 값은 같음

*. DataSourceConfig.java

	@Bean
	public JdbcTemplate jdbcTemplate() { // JDBC를 쉽게 연결하는 템플릿, Bean에서 직접 만드는 방식
		return new JdbcTemplate(dataSource());
	}

	@Bean
	public AddCustomerDao addCustomerDao() {
		return new AddCustomerDao(dataSource());
	}

*. AddCustomerDao.java

public class AddCustomerDao {
	private JdbcTemplate jdbcTemplate;

	public AddCustomerDao(DataSource dataSource) { // dataSource 를 직접 만드는 방식
		jdbcTemplate = new JdbcTemplate(dataSource);
	}

	public void addCustomer(Customer customer) {
		String sql = "INSERT INTO Customer (email, passwd, name, ssn, phone) VALUES (?, ?, ?, ?, ?)";

		jdbcTemplate.update(new PreparedStatementCreator() {

			@Override
			public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
				PreparedStatement pstmt = con.prepareStatement(sql);
				pstmt.setString(1, customer.getEmail());
				pstmt.setString(2, customer.getPasswd());
				pstmt.setString(3, customer.getName());
				pstmt.setString(4, customer.getSsn());
				pstmt.setString(5, customer.getPhone());

				return pstmt;
			}
		});
	}

	public void addCustomer2(Customer customer) { // 실전에서 쓰는 방법, 위의 방법과 값은 같음
		String sql = "INSERT INTO Customer (email, passwd, name, ssn, phone) VALUES (?, ?, ?, ?, ?)";
		jdbcTemplate.update(sql, customer.getEmail(), customer.getPasswd(), customer.getName(), customer.getSsn(),
				customer.getPhone());
	}

	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DataSourceConfig.class);
		AddCustomerDao dao = context.getBean("addCustomerDao", AddCustomerDao.class);
		Customer c = new Customer();
		c.setEmail("quan@java.com");
		c.setPasswd("3333");
		c.setName("관우");
		c.setSsn("206611-4564567");
		c.setPhone("010-9865-2889");
		dao.addCustomer2(c);
		System.out.println("-Inserted-");
		context.close();
	}
}

실습3

  • 3개의 클래스 전부 같은 값을 출력함

*. CustomerDao(1).java

  • RowMapper<Customer>() 를 각각의 메서드에 전부 입력하는 방법
public class CustomerDao {
	private JdbcTemplate jdbcTemplate;

	public CustomerDao(DataSource dataSource) {
		jdbcTemplate = new JdbcTemplate(dataSource);
	}

	public List<Customer> findAllCustomers() {
		String sql = "SELECT cid, email, passwd, name, ssn, phone, regDate FROM Customer";
		return jdbcTemplate.query(sql, new RowMapper<Customer>() {

			@Override
			public Customer mapRow(ResultSet rs, int rowNum) throws SQLException {
				Customer customer = new Customer(rs.getLong("cid"), rs.getString("email"), rs.getString("passwd"),
						rs.getString("name"), rs.getString("ssn"), rs.getString("phone"), rs.getTimestamp("regDate"));
				return customer;
			}
		});
	}

	public List<Customer> findCustomerByRegDate(Date regDate) {
		String sql = "SELECT cid, email, passwd, name, ssn, phone, regDate FROM Customer WHERE DATE(regDate)=?";
		return jdbcTemplate.query(sql, new RowMapper<Customer>() { // 여러개를 찾는 query

			@Override
			public Customer mapRow(ResultSet rs, int rowNum) throws SQLException {
				Customer customer = new Customer(rs.getLong("cid"), rs.getString("email"), rs.getString("passwd"),
						rs.getString("name"), rs.getString("ssn"), rs.getString("phone"), rs.getTimestamp("regDate"));
				return customer;
			}

		}, regDate);
	}

	public Customer findCustomerByEmail(String email) {
		String sql = "SELECT cid, email, passwd, name, ssn, phone, regDate FROM Customer WHERE email=?";
		return jdbcTemplate.queryForObject(sql, new RowMapper<Customer>() { // 하나만 찾는 queryForObject

			@Override
			public Customer mapRow(ResultSet rs, int rowNum) throws SQLException {
				Customer customer = new Customer(rs.getLong("cid"), rs.getString("email"), rs.getString("passwd"),
						rs.getString("name"), rs.getString("ssn"), rs.getString("phone"), rs.getTimestamp("regDate"));
				return customer;
			}

		}, email);
	}

	public long countCustomers() {
		String sql = "SELECT count(*) FROM Customer";
		return jdbcTemplate.queryForObject(sql, Long.class);
	}

*. CustomerDao(2).java

  • RowMapper<Customer>() 내용이 같기 때문에, 클래스로 만들어서 사용하는 방법
public class CustomerDao {
	private JdbcTemplate jdbcTemplate;

	public CustomerDao(DataSource dataSource) {
		jdbcTemplate = new JdbcTemplate(dataSource);
	}

	public List<Customer> findAllCustomers() {
		String sql = "SELECT cid, email, passwd, name, ssn, phone, regDate FROM Customer";
		return jdbcTemplate.query(sql, new CustomerRowMapper());
	}

	public List<Customer> findCustomerByRegDate(Date regDate) {
		String sql = "SELECT cid, email, passwd, name, ssn, phone, regDate FROM Customer WHERE DATE(regDate)=?";
		return jdbcTemplate.query(sql, new CustomerRowMapper(), regDate);
	}

	public Customer findCustomerByEmail(String email) {
		String sql = "SELECT cid, email, passwd, name, ssn, phone, regDate FROM Customer WHERE email=?";
		return jdbcTemplate.queryForObject(sql, new CustomerRowMapper(), email);
	}

	public long countCustomers() {
		String sql = "SELECT count(*) FROM Customer";
		return jdbcTemplate.queryForObject(sql, Long.class);
	}
}

*. CustomerRowMapper.java

public class CustomerRowMapper implements RowMapper<Customer> {

	@Override
	public Customer mapRow(ResultSet rs, int rowNum) throws SQLException {
		Customer customer = new Customer(rs.getLong("cid"), rs.getString("email"), rs.getString("passwd"),
				rs.getString("name"), rs.getString("ssn"), rs.getString("phone"), rs.getTimestamp("regDate"));
		return customer;
	}
}

*. CustomerDao(3).java

  • 모든 Bean Property를 담아주는 RowMapper을 자동으로 생성해주는 BeanPropertyRowMapper 사용
public class CustomerDao {
	private JdbcTemplate jdbcTemplate;

	public CustomerDao(DataSource dataSource) {
		jdbcTemplate = new JdbcTemplate(dataSource);
	}

	public List<Customer> findAllCustomers() {
		String sql = "SELECT cid, email, passwd, name, ssn, phone, regDate FROM Customer";
		return jdbcTemplate.query(sql, new BeanPropertyRowMapper<Customer>(Customer.class));
	}

	public List<Customer> findCustomerByRegDate(Date regDate) {
		String sql = "SELECT cid, email, passwd, name, ssn, phone, regDate FROM Customer WHERE DATE(regDate)=?";
		return jdbcTemplate.query(sql, new BeanPropertyRowMapper<Customer>(Customer.class), regDate);
	}

	public Customer findCustomerByEmail(String email) {
		String sql = "SELECT cid, email, passwd, name, ssn, phone, regDate FROM Customer WHERE email=?";
		return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Customer>(Customer.class), email);
	}

	public long countCustomers() {
		String sql = "SELECT count(*) FROM Customer";
		return jdbcTemplate.queryForObject(sql, Long.class);
	}
}
profile
안녕하세요. 맡은 업무를 확실하게 수행하는 웹 개발자가 되기 위하여 끊임없이 학습에 정진하겠습니다.

0개의 댓글

관련 채용 정보