[java] 자바에서 SQL 문자열을 만드는 가장 깨끗한 방법


6 Answers

임의의 SQL의 경우, jooq.org 사용 jooq.org . jOOQ는 현재 SELECT , INSERT , UPDATE , DELETE , TRUNCATEMERGE 합니다. 다음과 같이 SQL을 작성할 수 있습니다.

String sql1 = DSL.using(SQLDialect.MYSQL)  
                 .select(A, B, C)
                 .from(MY_TABLE)
                 .where(A.equal(5))
                 .and(B.greaterThan(8))
                 .getSQL();

String sql2 = DSL.using(SQLDialect.MYSQL)  
                 .insertInto(MY_TABLE)
                 .values(A, 1)
                 .values(B, 2)
                 .getSQL();

String sql3 = DSL.using(SQLDialect.MYSQL)  
                 .update(MY_TABLE)
                 .set(A, 1)
                 .set(B, 2)
                 .where(C.greaterThan(5))
                 .getSQL();

SQL 문자열을 얻는 대신 jOOQ를 사용하여 SQL 문자열을 실행할 수도 있습니다. 만나다

jooq.org

(면책 조항 : 나는 jOOQ 뒤에있는 회사에서 일하고있다)

Question

데이터베이스 조작 (업데이트, 삭제, 삽입, 선택, 일종의)을 수행하기위한 SQL 문자열을 작성하고 싶습니다 - 수백만 개의 "+"및 인용 부호를 사용하는 끔찍한 문자열 연결 방법 대신 - 읽을 수없는 - 더 나은 방법이어야합니다.

필자는 MessageFormat을 사용하는 것을 생각해 보았습니다.하지만 사용자 메시지에 사용하도록되어 있습니다. 합리적인 작업을 수행 할 것이라고 생각하지만, java SQL 라이브러리에서 SQL 형식 연산에 맞춰야합니다.

Groovy가 좋을까요?




필자는 임시보고 목적으로 매우 동적 인 SQL 문을 작성해야하는 Java 서블릿 응용 프로그램을 개발 중입니다. 이 앱의 기본 기능은 미리 지정된 쿼리에 이름이 지정된 HTTP 요청 매개 변수를 제공하고 멋지게 형식화 된 출력 표를 생성하는 것입니다. 스프링 MVC와 의존성 삽입 프레임 워크를 사용하여 모든 SQL 쿼리를 XML 파일에 저장하고 테이블 형식 정보와 함께보고 응용 프로그램에로드했습니다. 결과적으로보고 요구 사항은 기존 매개 변수 매핑 프레임 워크의 기능보다 복잡해졌으며 스스로 작성해야했습니다. 개발 과정에서 흥미로운 연습이었고 찾을 수있는 것보다 훨씬 강력하게 매개 변수 매핑을위한 프레임 워크를 만들었습니다.

새로운 매개 변수 매핑은 다음과 같이 보입니다.

select app.name as "App", 
       ${optional(" app.owner as "Owner", "):showOwner}
       sv.name as "Server", sum(act.trans_ct) as "Trans"
  from activity_records act, servers sv, applications app
 where act.server_id = sv.id
   and act.app_id = app.id
   and sv.id = ${integer(0,50):serverId}
   and app.id in ${integerList(50):appId}
 group by app.name, ${optional(" app.owner, "):showOwner} sv.name
 order by app.name, sv.name

결과 프레임 워크의 장점은 올바른 유형 확인 및 제한 검사를 통해 HTTP 요청 매개 변수를 직접 쿼리에 처리 할 수 ​​있다는 점입니다. 입력 유효성 검사를 위해 추가 매핑이 필요하지 않습니다. 위의 예의 쿼리에서 serverId 라는 매개 변수는 정수로 캐스팅되고 0-50 범위에 있는지 확인하기 위해 검사됩니다. appId 매개 변수는 길이 제한이 50 인 정수 배열로 처리됩니다. showOwner 필드가 있고 "true"로 설정된 경우 따옴표에있는 SQL 비트가 선택적 필드에 대해 생성 된 쿼리에 추가됩니다 매핑. 필드 추가 매개 변수 맵핑과 함 2 선택적 SQL 세그먼트를 포함하여 몇 가지 더 많은 매개 변수 유형 맵핑을 사용할 수 있습니다. 개발자가 생각해 낼 수있는 복잡한 쿼리 매핑을 허용합니다. 또한 지정된 쿼리가 PreparedStatement를 통해 최종 매핑을 가지는지 아니면 미리 작성된 쿼리로 실행되는지를 결정하기 위해 보고서 구성에 컨트롤이 있습니다.

샘플 Http 요청 값 :

showOwner: true
serverId: 20
appId: 1,2,3,5,7,11,13

그러면 다음 SQL이 생성됩니다.

select app.name as "App", 
       app.owner as "Owner", 
       sv.name as "Server", sum(act.trans_ct) as "Trans"
  from activity_records act, servers sv, applications app
 where act.server_id = sv.id
   and act.app_id = app.id
   and sv.id = 20
   and app.id in (1,2,3,5,7,11,13)
 group by app.name,  app.owner,  sv.name
 order by app.name, sv.name

Spring이나 Hibernate 또는 그 프레임 워크 중 하나가 타입을 검증하는 더 강력한 매핑 메커니즘을 제공하고, 배열과 같은 다른 기능과 같은 복잡한 데이터 타입을 허용해야한다고 생각합니다. 나는 나의 목적을 위해서만 내 엔진을 썼다. 현재 오라클 쿼리에서만 작동하며 모든 코드는 대기업에 속합니다. 언젠가 내 아이디어를 가지고 새로운 오픈 소스 프레임 워크를 구축 할 수는 있지만 기존의 빅 플레이어 중 한 명이 도전에 나설 것으로 기대하고 있습니다.




나는 둘째로 Hibernate와 같은 ORM을 사용하기위한 권장 사항을 제시한다. 그러나 그것이 작동하지 않는 상황이 분명하기 때문에이 기회를 통해 SqlBuilder 가 작성하는 데 도움이되는 몇 가지 정보를 SqlBuilder . SqlBuilder 는 "빌더"스타일을 사용하여 동적으로 SQL 문을 작성하는 Java 라이브러리입니다. 그것은 상당히 강력하고 공정하게 유연합니다.




Google은 매우 명확한 SQL 작성 방법을 제공하는 Room Persitence Library 라는 라이브러리 를 제공합니다. Bellow는 공식 웹 사이트의 간단한 코드입니다.

@Dao
public interface UserDao {
    @Query("SELECT * FROM user")
    List<User> getAll();

    @Query("SELECT * FROM user WHERE uid IN (:userIds)")
    List<User> loadAllByIds(int[] userIds);

    @Query("SELECT * FROM user WHERE first_name LIKE :first AND "
           + "last_name LIKE :last LIMIT 1")
    User findByName(String first, String last);

    @Insert
    void insertAll(User... users);

    @Delete
    void delete(User user);
}

라이브러리에 대한 공식 문서에는 더 많은 예제와 더 나은 문서가 있습니다.

자바 ORM 인 MentaBean이라고하는 것도 있습니다. 그것은 좋은 기능을 가지고 있으며 SQL을 작성하는 아주 간단한 방법 인 것 같습니다.




나는 네가 Squiggle 과 같은 무언가를 쫓고 있는지 궁금해하고있다. 또한 매우 유용한 것이 jDBI 입니다. 그래도 검색어를 사용하면 도움이되지 않습니다.




PreparedStatements의 긴 SQL 문자열을 제외하고 문자열 연결을 어떻게 얻습니까? (여러 줄로 나누는 텍스트 파일과로드로 쉽게 제공 할 수있는 리소스)

당신은 직접 SQL 문자열을 생성하지 않습니까? 그건 프로그래밍에서 가장 큰 no-no입니다. PreparedStatements를 사용하고 데이터를 매개 변수로 제공하십시오. 그것은 SQL 주입의 기회를 크게 줄입니다.




필자는 Spring의 Named JDBC Parameters를 사용하여 "select * from blah where colX = ': someValue'"와 같은 표준 문자열을 쓸 수 있습니다. 꽤 읽을 만하다고 생각합니다.

다른 방법으로는 문자열을 별도의 .sql 파일로 제공하고 유틸리티 메서드를 사용하여 내용을 읽는 것입니다.

오, Squill을 살펴볼 가치가 있습니다. https://squill.dev.java.net/docs/tutorial.html



Related