//Google AdSense

https://sethlee.tistory.com/3

 

AJAX 를 동기(Sync) 방식으로 사용하기

안녕하세요 용재형 입니다. 이번 포스팅은 AJAX 를 동기(Sync) 방식으로 사용하기 입니다. Ajax는 Asynchronous Javascript And XML 의 약자로, 일반적으로 클라이언트와 서버측의 데이터 전송 및 처리를 비��

sethlee.tistory.com

↑참고

 

ajax를 통해 비동기적으로 데이터를 주고받는 경우 그 데이터 수신이 완료될 때 까지 기다리지 않고 다른 작업을 진행하게 된다.

만약 ajax를 통신이 끝나고 모든 데이터를 받아 처리한 뒤에 다른 작업이 진행되길 원한다면 async: false 하여 동기화 하면 된다~ 

 

async가 아니라  sync니까 ajax가 아니라 sjax가 되는건가 ??

 

 

호스팅 받은 서버에 maven 빌드 파일을 올리고 tomcat 재맵핑을 했을 때

user block limit reached 오류로 정상적으로 mapping이 되지 않았다.

putty에서 처음 오류를 마주쳤을 땐 정말 무서웠다...!!!!!!!!!!!!!!!!!!!!!!!!!!

알아보니 웹하드 용량이 초과되어 발생하는 오류였다... 또르르 

 

해결 방법은 빌드된 파일 용량을 줄일 방법을 찾거나 추가결제로 웹하드 용량을 늘리는 수 밖엔 없다..

웹하드 용량 추가 결제 금액이 부담되는 정도는 아니므로 파일이 더 커지면 추가결제를 해야겠다.

'Diary' 카테고리의 다른 글

JUnit / TDD  (0) 2020.07.13
형상관리 ( SVN , GIT)  (0) 2020.07.08
호스팅 받은 웹에 프로젝트 배포했을 때 db 연결이 안되는 오류..  (0) 2020.06.26
dto  (0) 2020.06.17

제곧내...

 


<update id="companyBoardCountUpadate" parameterType="CompanyBoardContent">
	<selectKey order="BEFORE" keyProperty="companyCount" resultType="String">		
		SELECT 
			c.company_count+1
			from
				tb_company AS c
			where
				c.company_code = #{companyCode}
	</selectKey>
    
    UPDATE tb_company
    	SET
    		company_count= #{companyCount}
    	WHERE 
    		company_code = #{companyCode}
            
</update>

쿼리문도 전부 정상이고 오탈자도 없으며,, DTO에 알맞은 getter, setter도 전부 있었는데!!!!!!!!!!!

org.apache.ibatis.executor.ExecutorException: No setter found for the keyProperty 'companyCount' in java.lang.String.

이 오류로 인해 진행이 안되는 상황이었다..

조언도 구해봤는데 원인을 전혀 모르겠어서 서브쿼리로 처리했다...

마이바티스!!!!!! 나는 너를 믿었는데!! 

 

그래도 서브쿼리로 바꾼 코드가 더 간결해서 기분이 좋아졌다 ~~ ^^~!!

<update id="companyBoardCountUpadate" parameterType="CompanyBoardContent">
	UPDATE tb_company
		SET
			company_count= (SELECT company_count +1)
		WHERE 
			company_code = #{companyCode}
</update>

 

'SpringBoot' 카테고리의 다른 글

[SpringBoot] Batch study...!  (0) 2021.04.28
[SpringBoot] Batch  (0) 2021.04.27
[mybatis] multiple select key  (0) 2020.06.23
파일 업로드  (0) 2020.06.19
package kr.or.ksmart;

class Member{
	//인스턴스변수, 멤버필드
	private String memberName;
	//생성자메서드
	public Member(String memberName) {
		this.memberName = memberName;
	};
	//메서드
	public String getMemberName () {
		return memberName;
	};	
}

class User{
	//생성자메서드를 접근지정자 private으로 선언 시 외부에서 객체화 불가능  
	private User() {
		
	};
	
	public static User getInstance() {
		return new User();
	};
}

public class JavaEx01 {

	public static void main(String[] args) {
		/*
		 * 복습1. Member라는 클래스를 생성할 것이다.
		 * 이 Member라는 클래스는 인스턴스화 할 때 매개변수 1개를 받아야만 인스턴스화가 가능하다.
		 * 또한 Member 클래스는 인스턴스변수 memberName 그리고 getMemberName이라는 메서드를 가지게 된다.
		 * 위의 조건대로 클래스를 생성하고 선언과 호출을 하도록 하여라.
		 * (인스턴스화 할 때 들어간 인수값은 인스턴스변수에 저장된다.)
		 */
		
		Member member = new Member("김최첨단");
		System.out.println(member.getMemberName());
		
		/*
		 * 복습2. User클래스를 생성할 것이다.
		 * 이 User클래스는 new 연산자를 통하여 인스턴스화 할 수 없으며, getInstance라는 메서드를 통해서 인스턴스화 가능하다.
		 * 이 클래스를 선언하고 인스턴스화를 시키도록 하여라.
		 */
		
		User user = User.getInstance();
		System.out.println(user+"<<-user");

		/*
		 * 복습3. 래퍼클래스가 무엇인지 서술하시오.
		 * 
		 * 기본형 타입의 데이터를 객체로 취급하기 위해 사용하는 클래스. 
		 * 클래스변수와 클래스메서드 위주로 다 
		 */
		
		/*
		 * 복습4. 인스턴스변수와 클래스변수 차이점을 서술하시오.
		 * 인스턴스변수 : 인스턴스화 되어야 접근 가능한 변수
		 * 클래스변수 : 인스턴스화 하지 않아도 접근 가능한 변수
		 * 
		 * 인스턴스변수는 클래스가 인스턴스화 될 때마다 함께 새로이 인스턴스화 되는 변수이고
		 * 클래스변수는 정적으로 선언되어있어, 한 번 인스턴스화된 주소값을 변동없이 가리키는 변수이다.
		 */
		
		/*
		 * 복습5. class로 변환된(바이트 코드) 파일을 실행시키거나, java 프로그래밍의 메모리를 관리하는 프로그램의 명칭이 무엇인가요?
		 * 
		 * Java Virtual Machine 
		 */
	}

}
package kr.or.ksmart;

class MemberSuper{
	public String getMemberName() {
		return null;
	}
	
	public final int getMemberAge() {
		return 0;
	}
	
	public void setMemberAddr(String addr1) {

	}
	public void setMemberAddr(String addr1, String addr2) {
		
	}
	
}

class MemberSub extends MemberSuper {
	@Override
	public String getMemberName() {
		return null;
	}
	
	/*public int getMemberAge() {
		return 0;
	}*/
}

public class JavaEx02 {
	public static void main(String[] args) {
		/*
		 * 복습6. MemberSuper클래스와 MemberSub클래스가 있다.
		 * MemberSub는 MemberSuper의 멤버를 가지고 있다.
		 * 위의 설명에 맞는 클래스를 선언하고 호출하도록 하여라. 
		 */
		/*
		 * 복습7. 복습6의 클래스의 관계에서 추가적인 메서드를 생성할 것이다.
		 * MemberSuper 클래스에 getMemberName과 getMemberAge라는 메서드가 있다.
		 * MemberSub 클래스에서  getMemberName 오버라이딩은 가능하나, getMemberAge는 오버라이딩이 불가능하다.
		 * 위의 설명에 알맞게 메서드를 작성하여라.
		 */
		/*
		 * 복습8. 복습6의 클래스의 관계에서 추가적인 메서드를 생성할 것이다.
		 * setMemberAddr 메서드가 1개의 매개변수를 받을 수도 있고
		 * setMemberAddr 메서드가 2개의 매개변수를 받을 수도 있다.
		 * 메서드를 알맞게 작성하여라. >>메서드오버로딩
		 */
	}
}
package kr.or.ksmart;

interface In1{
	public int in1();
}
interface In2{
	public int in2();
}

class InIm implements In1, In2 {

	@Override
	public int in2() {
		return 0;
	}

	@Override
	public int in1() {
		return 0;
	}
	
}

public class JavaEx03 {
	public static void main(String[] args) {
		/*
		 * 복습9. 인터페이스 2개를 상속받은 클래스를 생성할 것이다.
		 * 인터페이스의 명은 In1, In2 이며 
		 * int 형을 리턴하는 In1 인터페이스의 in1 메서드, In2 인터페이스의 in2 메서드를 가지고 있다.
		 * InIm으로 클래스를 생성하고 2개의 인터페이스를 상속받아 객체화할 수 있도록 만들어라.
		 * 또한 InIm를 객체화하고 In1, In2를 업캐스팅 하도록 하여라
		 */
		InIm inIm = new InIm();
		
		In1 in1 = inIm;
		In2 in2 = inIm;
		
		/*
		 * 복습10. 객체지향의 4대 원칙을 서술하시오.
		 * 캡슐화, 추상화, 상속, 다형성
		 */
		
		/*
		 * 복습11. 객체지향 설계의 5대 원칙을 서술하시오.
		 * SOLID
		 * 1. SRP(단일 책임 원칙) - 소프트웨어의 설계 부품(클래스, 함수 등)은 단 하나의 책임만을 가져야 한다.
		 * 2. OCP(개방-폐쇄 원칙) - 기존의 코드를 변경하지 않고(Closed) 기능을 수정하거나 추가할 수 있도록(Open) 설계해야 한다. > getter, setter
		 * 3. LSP(리스코프 치환 원칙) - 자식 클래스는 부모클래스에서 가능한 행위를 수행할 수 있어야 한다. > 업캐스팅과 관련
		 * 4. ISP(인터페이스 분리 원칙) - 한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다. 하나의 일반적인 인터페이스 보다 여러 개의 구체적인 인터페이스가 낫다.
		 * 5. DIP(의존 역전 원칙) - 의존 관계를 맺을 때, 변화하기 쉬운 것 보다 변화하기 어려운 것에 의존해야 한다는 원칙이다.
		 */
		
	}
}

 

'JAVA' 카테고리의 다른 글

[Jsoup] 스크랩핑 해보께  (0) 2021.05.03
JUnit Mockito Framework  (0) 2021.04.27
[JAVA Basic] Generic  (1) 2020.05.22
[JAVA Basic] Singleton Pattern  (0) 2020.05.20

get방식으로 전송한 데이터를 alert 창에 넣고싶었다!

 

location.href로 받아온 uri에서 '?키=값'을 가져오는 일은 수월했다

하지만 값에 띄어쓰기가 있어 '등록된+정보가+없습니다.' 와 같은 식으로 추출되었다.

 

replace를 통해 +를 공백으로 치환하는 작업을 자동으로 하기 위해

match 함수를 사용하려고 하였는데 match는 정규식을 인식하기 때문인지 +를 문자열로 받아주질 않았다..

 

 

그래서 정규표현식을 사용해버리기로 했다~

//로그인 실패시 alert ()
		
		var message = null;
		//uri에서 get방식으로 넘긴 값 추출
		var uri = decodeURI(location.href);
		var get = uri.substr(uri.indexOf('?')+1);
		if(uri != get){
			message = get.substr(get.indexOf('=')+1);
		};
		//.을 제외한 특수문자 정규식
		var regExp = /[\{\}\[\]\/?,;:|\)*~`!^\-+<>@\#$%&\\\=\(\'\"]/gi;
		if(regExp.test(message)){
			//.을 제외한 특수문자를 공백으로 치환
			message = message.replace(regExp,' ');
		};
		//추출한 값이 null이 아닐 경우 alert창 출력
		if(message != null){
				alert(message);
		};

test를 통해 .을 제외한 특수문자 정규식과 message의 문자열과 비교해 특수문자 여부를 파악하고

message에 특수문자가 있다면 정규식에 기술한 특수문자들을 공백으로 바꾸는 식을 만들었다!

 

결과는 성공~

정규식 참고!

https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/%EC%A0%95%EA%B7%9C%EC%8B%9D

 

정규 표현식

정규 표현식은 문자열에 나타는 특정 문자 조합과 대응시키기 위해 사용되는 패턴입니다. 자바스크립트에서, 정규 표현식 또한 객체입니다.  이 패턴들은 RegExp의 exec 메소드와 test 메소드  ,��

developer.mozilla.org

 

application.properties 

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://호스팅받은주소:3306/tnwl6609?serverTimezone=UTC&characterEncoding=UTF8

프로퍼티에서 datasource url을 위와 같이 호스팅받은 주소로 설정했더니

db와 연결된 페이지를 호출할 때 마다 아래와 같은 오류가 발생.

### Error querying database.  Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: Access denied for user '아이디'@'아이피' (using password:YES)

 

application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/tnwl6609?serverTimezone=UTC&characterEncoding=UTF8

datasource url을 호스팅 받은 주소에서 localhost로 바꾸어주니 잘 작동된다!

'Diary' 카테고리의 다른 글

형상관리 ( SVN , GIT)  (0) 2020.07.08
user block limit reached 오류  (0) 2020.07.01
dto  (0) 2020.06.17
api xml 형태 parsing 하기  (0) 2020.06.16
<!-- 처리업무 등록 -->
	<insert id="unpaidInsert" parameterType="Unpaid">
		
		<!-- unpaidCode -->
		<selectKey order="BEFORE" keyProperty="unpaidCode" resultType="String">
			select
				(case count(*)
				when 0 then 'unpaid_1'
				else CONCAT('unpaid_',max(cast(substring(unpaid_code,8) as decimal))+1)
				end) as unpaidCode
			from
				tb_unpaid
		</selectKey>
		<selectKey order="BEFORE" keyProperty="customerCode" resultType="String">
			SELECT
				c.customer_code
			from
				tb_customer AS c
				where
					#{customerName} = c.customer_name
					and
					#{customerTel} = c.customer_tel
		</selectKey>
		<selectKey order="BEFORE" keyProperty="unpaidRegStaffCode" resultType="String">
			SELECT
				sf.staff_code
			from
				tb_staff as sf
				join
				tb_member as m
				on
				sf.member_id = m.member_id
				join
				tb_store AS sr
				on
				sf.store_code =sr.store_code
			where
				#{unpaidRegMemberName} = m.member_name
				and
				#{unpaidRegStoreName} = sr.store_name	
		</selectKey>

		INSERT INTO tb_unpaid
			(unpaid_code
			, unpaid_exp_date
			, unpaid_part
			, unpaid_sub_name
			, unpaid_desc
			, customer_code
			, unpaid_memo
			, unpaid_status
			, unpaid_reg_date
			, unpaid_reg_staff_code)
		VALUES 
			(#{unpaidCode}
			, NOW()
			, #{unpaidPart}
			, #{unpaidSubName}
			, #{unpaidDesc}
			, #{customerCode}
			, #{unpaidMemo}
			, #{unpaidStatus}
			, NOW()
			, #{unpaidRegStaffCode})

	</insert>

mapper.xml 에서 <insert></insert> 안에 <selectKey></selectKey>를 여러개 사용하여 여러가지의 조인 값을 가져오고싶었다! 하지만 계속 오류가 발생했다.

알고보니 <selectKey></selectKey> 는 한개만 사용할 수 있다고 한다!!


<!-- 처리업무 등록 -->
	<insert id="unpaidInsert" parameterType="Unpaid">
		<selectKey order="BEFORE" keyProperty="unpaidCode,customerCode,unpaidRegStaffCode" resultType="Map">
			select
				(case count(*)
				when 0 then 'unpaid_1'
				else CONCAT('unpaid_',max(cast(substring(unpaid_code,8) as decimal))+1)
				end) as unpaidCode
				,tc.customer_code as customerCode
				,tc.staff_code as unpaidRegStaffCode
			from
				tb_unpaid AS u ,(
							SELECT
								c.customer_code,
								tf.staff_code
							from
								tb_customer AS c,
								(
								SELECT
								sf.staff_code
								from
									tb_staff as sf
									join
									tb_member as m
									on
									sf.member_id = m.member_id
									join
									tb_store AS sr
									on
									sf.store_code =sr.store_code
								where
									#{unpaidRegMemberName} = m.member_name
									and
									#{unpaidRegStoreName} = sr.store_name
									)AS tf
			where
				#{customerName} = c.customer_name
				and
				#{customerTel} = c.customer_tel
				)AS tc
		</selectKey>

		INSERT INTO tb_unpaid
			(unpaid_code
			, unpaid_exp_date
			, unpaid_part
			, unpaid_sub_name
			, unpaid_desc
			, customer_code
			, unpaid_memo
			, unpaid_status
			, unpaid_reg_date
			, unpaid_reg_staff_code)
		VALUES 
			(#{unpaidCode}
			, NOW()
			, #{unpaidPart}
			, #{unpaidSubName}
			, #{unpaidDesc}
			, #{customerCode}
			, #{unpaidMemo}
			, #{unpaidStatus}
			, NOW()
			, #{unpaidRegStaffCode})
	</insert>

그래서 서브쿼리를 사용하여 여러개의 컬럼을 한개의 selectKey에 담았다.

insert 쿼리문에서 값을 받을 때 #{paramater}와 selectKey의 select문의 alias가 대응된다~!!


친구랑 대화하다보니 하나의 서비스에서 처리하지 않고 서비스를 나누어서 처리하는 방법도 있을 거라고 깨달았다!!

서비스를 나누어 처리하면 서브쿼리를 쓰지 않고도 처리할 수 있을 것이다.

서비스를 하나로 만들면 서비스를 나눈 것 보다 유지보수 측면에서 이득이라고 하니 상황에 따라 골라서 사용해야겠다.

또, 요즘 join이 없도록 작업하는 추세라고 하는데!!

정규화를 막 배운 입장에서는 아직 실제로 사용하기에는 정규화가 마음에 걸린다...

하지만 서브쿼리 안에!! 서브쿼리 안에!! 서브쿼리를 넣다 보니 join이 없는 작업이 더 편리할 것 같다고 느꼈다.

지금 하고있는 프로젝트는 작은 규모이기 때문에 데이터베이스에 데이터가 적어서 체감을 못했지만, join이 많이 일어나면  데이터가 많이 존재할 경우 처리속도가 느려진다고 하니 참고해야겠다!!

 

 

 

+ Recent posts