1. vscode에서 html파일로 실행시키기

핵심. 카카오에서 제공하는 src 주소에서 "http:"추가하기

url에서 "//"더블대쉬는 기존or현재 페이지가 사용한 프로토콜을 사용해서 따로 프로토콜을 입력해주지 않아도 되는 이점이 있으나 이전에 https페이지를 사용했다면 https로 프로토콜을 자동으로 해주기 때문에 api가 연결이 안 됐던 것!  그래서 소스코드에 http:를 추가해줬더니 됐다. 

2. intellij 프로젝트 안에서 jsp파일로 실행시키기

핵심. controller추가하고 security 패싱 추가하기.

 

1.2.3 DB 커넥션 만들기의 독립

  • 상속을 통한 확장 -> 소스의 비공개, 변화에 대응
  • 추상 클래스와 추상 메소드를 통한 클래스의 상속으로 서브클래스에서 원하는 방식대로 구현. 
public abstract class UserDao {

    public abstract Connection getConnection() throws ClassNotFoundException, SQLException;
    
    public void add(User user) throws~
    public User get(String id_ throws~
    
    }
public class NUserDao extends UserDao{
	public Connection getConnection() throws ClassNotFoundException, SQLEception{
    //N사 DB connection 생성코드
    }
 }

▶중복 코드의 메소드 추출

private Connection getConnection() throws ClassNotFoundException, SQLException{
    Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    c = DriverManager.getConnection("jdbc:sqlserver:///xx.database.windows.net:1433; databaseName=xx-03-15T00-46Z; user=xx; password=xx@;" );
    return c;
}

분리하면 1433포트 찾을 수 없다고 하는 마법..

com.microsoft.sqlserver.jdbc.SQLServerException: 호스트 /xx.database.windows.net, 포트 1433에 대한 TCP/IP 연결에 실패했습니다. 오류: "/xx.database.windows.net. 연결 속성을 확인하세요. SQL Server의 인스턴스가 호스트에서 실행되고 있고 포트에서 TCP/IP 연결을 허용하고 있는지 확인하세요. 또한 방화벽에서 포트로의 TCP 연결을 차단하지 않는지 확인하세요.".

*리팩토링 : 기존의 코드를 외부의 동작방식에는 변화 없이 내부 구조를 변경해서 재구성하는 작업 또는 기술을 말함.

*메소드 추출 기법 : 리팩토링 기법중 공통의 기능을 담당하는 메소드로 중복된 코드를 뽑아내는 것

- userDao main 실행 관련(with chatGpt)

//실행환경
ide : intellij,
jdk : 11
build tool : gradle
frameWork : springBoot 2.7.8

우여곡절 끝에 에러없이 실행 완료

발생 errors

1. classNotFoundException

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

안에 문구를 어느 티스토리를 보고 "서버이름.database.windows.net" 이런식으로 내가 만든azure 서버이름을 넣어야 한다고 해서 넣었었다가 발생한 에러... 

+ project structure > libraries > 프로젝트이름.main() 에 jdbc.jar 파일 추가해줘야 한다. 프로젝트 or 프로젝트.main() 누가지 선택지가 나오는데 전자는 안되는데 이유는 잘 모르겠는데 나중에 알게되면 수정하겠다.

2. bootjar , Entry META-INF/MANIFEST.MF is a duplicate but no duplicate handling strategy has been set  

chatgpt 형님께서  build.gradle에 

bootJar {
    duplicatesStrategy = 'exclude'
}

이거 추가하라고 해서 추가했더니 사라졌다.

이후 chatGpt형님의 코드리뷰를 받아 다시 작성한 아래 코드.

package com.toy.world.dao;

import com.toy.world.User;

import java.sql.*;
public class UserDao {
    public void add(User user) throws SQLException, ClassNotFoundException {
        Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
        Connection c=null;
        PreparedStatement ps=null;
        try {
        c = DriverManager.getConnection(
                "jdbc:sqlserver://서버이름.database.windows.net; databaseName=아주르디비리소스네임; user=내가설정한서버관리자이름; password=암호;");

        ps = c.prepareStatement(
                "insert into users(id, name, password) values(?,?,?)");
            ps.setString(1, user.getId());
            ps.setString(2, user.getName());
            ps.setString(3, user.getPassword());
            ps.executeUpdate();

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (ps != null) {
                ps.close();
            }
            if (c != null) {
                c.close();
            }
        }
    }

    public User get(String id) throws SQLException, ClassNotFoundException {
        Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
        Connection c = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            c = DriverManager.getConnection(
                    "jdbc:sqlserver://서버이름.database.windows.net; databaseName=아주르디비리소스네임; user=내가설정한서버관리자이름; password=암호;");

            ps = c.prepareStatement(
                    "select * from users where id=?"
            );
            ps.setString(1, id);
            rs = ps.executeQuery();
            rs.next();
            User user = new User();
            user.setId(rs.getString("id"));
            user.setName(rs.getString("name"));
            user.setPassword(rs.getString("password"));

            return user;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (rs!=null) {
                rs.close();
            }
            if(rs!=null){
                ps.close();
            }
            if(c!=null){
                c.close();
            }
        }
        return null;
    }

    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        UserDao dao = new UserDao();

        User user = new User();
        user.setId("myID");
        user.setName("내이름");
        user.setPassword("myPw");

        dao.add(user);

        System.out.println(user.getId()+"등록성공");

        User user2 = dao.get(user.getId());
        System.out.println(user2.getName());
        System.out.println(user2.getPassword());
        System.out.println(user2.getId()+"조회성공");

    }
}

알게된 것

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

>>관련 jdbc.jar 파일 안에 있는 클래스파일. 그리고 jar가 classpath에 추가되어 있어야 한다. 

> try catch finally 구문 사용법에 관한 디테일  

>> close 해주기 전에 널체크 해주기. why? 널포인트 체크해주기 위해 .

알아볼 문제

Connection c = DriverManager.getConnection(
                "jdbc:sqlserver://응.database.windows.net:[1433]; databaseName=ㅁㄴㅇ; user=ㅁㄴㅇ; password=ㅁㄴㅇ@;");

>포트 있고 없고 잘 돌아감. >>

> chatgpt "I see, thank you for clarifying. In that case, the Class.forName() method call is not necessary, as it's typically used to load the JDBC driver class for the specific database being used. Instead, you should use the DriverManager.getConnection() method to establish a connection to your SQL Server database, like you're already doing in the code."  >>  classNotFoundException 있고 없고 연관성 

 

그외 gpt선생님과의 resolution을 위한 질답

더보기

could you review my code? package com.toy.world.dao;

import com.toy.world.User;

import java.sql.*;

public class UserDao {
    public void add(User user) throws ClassNotFoundException, SQLException {
        Class.forName("응.database.windows.net");
        Connection c = DriverManager.getConnection(
                "jdbc:sqlserver://localhost/springbook", "spring", "book");

        PreparedStatement ps = c.prepareStatement(
                "insert into user(id, name, password) values(?,?,?)");
        ps.setString(1, user.getId());
        ps.setString(2, user.getName());
        ps.setString(3, user.getPassword());

        ps.executeUpdate();

        ps.close();
        c.close();
    }


Save & Submit

Cancel
Based on the code you provided, it appears to be responsible for adding a new user to a SQL Server database. Here are a few comments on the code:

ClassNotFoundException
The ClassNotFoundException in the add method suggests that you're attempting to load a JDBC driver class for your SQL Server database. However, the class name provided seems to be incorrect - it should be the fully qualified name of the JDBC driver class. For example, if you're using the Microsoft SQL Server JDBC Driver, the class name would be com.microsoft.sqlserver.jdbc.SQLServerDriver.

SQL injection vulnerability
The PreparedStatement used to execute the insert statement is a good way to prevent SQL injection attacks. However, you're not validating the user input for the three parameters passed to the statement. If any of these values contain malicious SQL code, they will be executed against your database, potentially leading to data loss or theft. It's important to sanitize user input before passing it to a database statement.

Connection management
It's generally a good practice to use connection pooling to manage database connections, rather than creating a new connection for each operation. This can improve performance and reduce the overhead of creating and tearing down database connections. You might want to look into using a connection pool library, such as HikariCP or Apache DBCP.

Resource cleanup
It's important to ensure that database resources are properly cleaned up after use, regardless of whether an exception is thrown or not. In this case, the PreparedStatement and Connection objects should be closed in a finally block to ensure they're always released, even if an exception occurs.

Overall, the code appears to be functional for adding a new user to a SQL Server database, but there are a few areas where it could be improved for performance, security, and resource management.




 Kim
".database.windows.net" is my server name
I see, thank you for clarifying. In that case, the Class.forName() method call is not necessary, as it's typically used to load the JDBC driver class for the specific database being used. Instead, you should use the DriverManager.getConnection() method to establish a connection to your SQL Server database, like you're already doing in the code.

So the corrected code




Kim
i modified like this "public class UserDao {
    public void add(User user) throws SQLException {
        //Class.forName(".database.windows.net");
        try {
        Connection c = DriverManager.getConnection(
                "jdbc:sqlserver://.database.windows.net:1433; databaseName=; user=; password=gmldnjs4@;");

        PreparedStatement ps = c.prepareStatement(
                "insert into user(id, name, password) values(?,?,?)");
            ps.setString(1, user.getId());
            ps.setString(2, user.getName());
            ps.setString(3, user.getPassword());
            ps.executeUpdate();

        }catch (NullPointerException ne){
            ne.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(user.getId()!=null && user.getName() != null && user.getPassword() != null){
                ps.close();
                c.close();
            }
        }
    }" correct please
The updated code looks better. Here are a few additional comments:

Connection string
The connection string you're using looks correct, assuming that your SQL Server instance is listening on port 1433 and that you have a valid username and password for the database.

Exception handling
Your exception handling looks good - you're catching specific exceptions and printing the stack trace, which is a good way to debug issues. However, it's unclear what you're trying to achieve with the NullPointerException catch block. It's best to avoid catching NullPointerExceptions unless you have a good reason to do so, as they typically indicate a programming error that should be fixed.

Resource cleanup
The finally block is a good way to ensure that database resources are cleaned up properly, regardless of whether an exception occurs or not. However, it's possible that the ps and c variables may be null if an exception is thrown before they are initialized. To avoid this, you can declare them outside the try block and assign null as their initial value, like this:

java
Copy code
Connection c = null;
PreparedStatement ps = null;
try {
    c = DriverManager.getConnection(/* connection string */);
    ps = c.prepareStatement(/* SQL statement */);
    // ...
} catch (SQLException e) {
    // handle exception
} finally {
    try { ps.close(); } catch (Exception e) { }
    try { c.close(); } catch (Exception e) { }
}
This ensures that the close() method is only called on initialized objects.

Overall, the code looks good and should be able to add a new user to your SQL Server database.




Kim
'ps' and 'c' cannot find symbol
I apologize for that mistake. You need to declare the ps and c variables outside of the try-catch block to access them in the finally block. Here's the corrected code:

java
Copy code
public class UserDao {
    public void add(User user) throws SQLException {
        Connection c = null;
        PreparedStatement ps = null;
        try {
            c = DriverManager.getConnection(
                "jdbc:sqlserver://.database.windows.net:1433; databaseName=; user=; password=gmldnjs4@;");
            ps = c.prepareStatement(
                "insert into user(id, name, password) values(?,?,?)");
            ps.setString(1, user.getId());
            ps.setString(2, user.getName());
            ps.setString(3, user.getPassword());
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            if (ps != null) {
                ps.close();
            }
            if (c != null) {
                c.close();
            }
        }
    }
}
In this corrected code, the ps and c variables are declared before the try-catch block and initialized to null. Then, in the finally block, it checks whether the objects have been initialized before attempting to call the close() method on them. This ensures that the close() method is only called on initialized objects, avoiding the "cannot find symbol" error.




Kim
why should i check 'ps' and 'c' null
It's important to check whether ps and c are null before calling their close() method in the finally block because there's a chance that an exception could be thrown before they're initialized.

For example, if an exception is thrown when you're establishing a connection to the database, then the ps and c variables will remain null. If you don't check whether they're null before calling their close() method in the finally block, then you'll get a NullPointerException when the method tries to call close() on an uninitialized object.

By checking whether ps and c are null before calling their close() method, you ensure that the close() method is only called on initialized objects, avoiding the NullPointerException.




Kim
"java.sql.SQLException: No suitable driver found for jdbc:sqlserver://.database.windows.net:1433; databaseName=; user=; password=gmldnjs4@;" occurs
The error "java.sql.SQLException: No suitable driver found" occurs because the JDBC driver for SQL Server has not been loaded. You need to make sure that you have added the JDBC driver JAR file to your project's classpath.

Here are the steps to add the JDBC driver JAR file to your project's classpath:

Download the JDBC driver JAR file for SQL Server from the Microsoft website.

Add the JDBC driver JAR file to your project's classpath. You can do this in different ways depending on the build tool you are using. Here are some examples:

If you're using Maven, you can add the following dependency to your pom.xml file:

php
Copy code
<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>9.4.1.jre15</version>
</dependency>
If you're using Gradle, you can add the following dependency to your build.gradle file:

python
Copy code
implementation 'com.microsoft.sqlserver:mssql-jdbc:9.4.1.jre15'
If you're not using any build tool, you can add the JDBC driver JAR file to your project's classpath manually. You can do this by copying the JAR file to a directory that's included in your project's classpath, such as the lib directory in your project's root directory.

Once you have added the JDBC driver JAR file to your project's classpath, try running your code again. The error "java.sql.SQLException: No suitable driver found" should be resolved.




Kim
im using gradle and i added this jdbc zip file"sqljdbc_12.2.0.0_kor"  on project structure -> libraries
When using Gradle, you can include the JDBC driver JAR file as a dependency in your build.gradle file.

Assuming you have added the sqljdbc_12.2.0.0_kor JDBC driver ZIP file to the lib directory of your project, you can add the following dependencies to your build.gradle file:

java
Copy code
dependencies {
    // other dependencies...
    compile files('lib/sqljdbc_12.2.0.0_kor/sqljdbc_12.2/enu/mssql-jdbc-9.4.1.jre15.jar')
}
This assumes that the JAR file inside the ZIP file is called mssql-jdbc-9.4.1.jre15.jar. If the actual name of the JAR file is different, you should replace the filename in the compile files() line accordingly.

Once you have added the dependency, run gradle build to download and include the JDBC driver JAR file in your project.

나의 경우는 controller 부분에서 pageNum이라는 파라미터 안 보내서 생겼음.

구현목표 : 동영상 URL 입력 받은 후 출력.

textarea에 입력한 URI 값 db에 저장 varchar2 형식이고 DTO변수는 String 타입

문제 :  DB에 저장된 URL 값만 [unread], 못 가져오고 있음.

 해결 : dto, sql컬럼명 연결시켜줌.  핵심은 빨간 부분 일치시켜줌.

db 저장 값 가져오기 성공

<form action="/recipe/writePro" method="post" > '정상'

☞  <form action="/recipe/writePro" method="post" enctype="multipart/form-data"> '에러'

>> form에서 encType="multipart/form-data" 로 전송하게 되면 DTO가 자동으로 생성/주입되지 않는다.

>>dto에 filename을 받는 변수명과 input file="name"이 동일하면 발생한 문제.

>>왜 같으면 저런 에러가 발생하는 지는 자세히는 모르겠다.. 알아볼 문제

 

target 폴더에 대해서 알아보다가 관련 검색글에 ctrl+shit+R 단축키를 눌러서 파일을 검색할시 이 폴더에 class파일도 검색되어서 불편하다고 리소스 필터에 target폴더를 등록해여 검색에서 제외되게끔 해준다는 글을 보았다.

밑져야 본전이란 마음으로 나도 해볼까 하고 설정해줬다. 그러니깐 generated-sources 폴더가 사라지면서 컨트롤러 매핑이 안됨. 다른 프로젝트 폴더보면 이 부분이 아예 없음. 

그렇다면 이게 왜 갑자기 나한테 있는거고 이전 프로젝트는 왜 없이도 잘 돌아갔는지 의문... 이프로젝트 설정내용 그대로 가져다 쓴거라 더 의문..

/프로젝트/generated-sources/annotaions

/target/generated-sources/annotations/

구글링 해봐도 한글 내용은 없고 영어 내용인데 정확히 뭘 하는 폴더인지 설명을 못 찾겠다..

등록 안 했을때 나오는 매핑
등록하면 사라지는 매핑

 

이외에도 오류 여러개가 나올텐데 히카리 어쩌고 저쩌고 등등

인터넷 검색해봐도 무슨 경로니 뭐니 다 해당이 나한테는 안됐었음. 

결론 : OJDBC10.jar 추가

추가한 모습
추가한 모습

에러 사라짐 휴~

상황 : 기존 프로젝트 안에 이름만 다른 같은 구현내용의 패키지 생성

게시판 리스트를 보여주는 MVC 패키지 작성

기존 Board : controller, bean. mybatis, service 모델 패키지

새로만든 Aboard : controller, bean. mybatis, service 모델 패키지

에러 발생

번역해도 무슨 뜻인지 잘 모르겠다.

하루 통을 날리고 다시 패키지 만들고 잘 클론 코딩 하고 부족한 부분 찾아봄.

                            <에러전문>
WARN : org.springframework.web.context.support.XmlWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: 컨텍스트 초기화 중 예외가 발생했습니다. org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ATeamServiceImpl': Unsatisfied dependency expressed through field 'mapper'; '매퍼' 필드를 통해 표현된 충족되지 않은 종속성; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'a.team.mybatis.AboardMapper' available: 사용 가능한 'a.team.mybatis.AboardMapper' 유형의 적합한 빈이 없습니다. expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: autowire 후보에 해당하는 최소한 1개의 bean이 필요합니다. 종속성 주석 {@org.springframework.beans.factory.annotation.Autowired(required=true)} ERROR: org.springframework.web.context.ContextLoader - Context initialization failed org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ATeamServiceImpl': Unsatisfied dependency expressed through field 'mapper'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'a.team.mybatis.AboardMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'a.team.mybatis.AboardMapper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

해법

root-context.xml에   

<mybatis-spring:scan base-package="org.mvc.mybatis" /> <<기존
<mybatis-spring:scan base-package="a.team.mybatis" /> <<추가(어제 했던거 같은데.. 하두 뇌절이 와서 기억도 안남..)

mybatis 어노테이션을 스캔해주고 mybatis 인터페이스를 스캔해서 구현해준다. 

+ Recent posts