====== MS SQL Server JDBC ======
* [[:mssqlserver|MS SQL Server]] JDBC Driver
* [[https://docs.microsoft.com/en-us/sql/connect/jdbc/microsoft-jdbc-driver-for-sql-server-support-matrix?view=sql-server-2017|Microsoft JDBC Driver for SQL Server Support Matrix]] JDBC 드라이버 지원 Java 버전 및 지원 기간.
* [[https://docs.microsoft.com/en-us/sql/connect/jdbc/programming-guide-for-jdbc-sql-driver|Microsoft JDBC Driver for SQL Server]]
* [[https://docs.microsoft.com/en-us/sql/connect/jdbc/download-microsoft-jdbc-driver-for-sql-server|SQL Server 용 Microsoft JDBC Driver를 다운로드]]
compile("com.microsoft.sqlserver:mssql-jdbc:6.4.0.jre8")
// Spring boot
ext['mssql-jdbc.version'] = '6.4.0.jre8'
compile("com.microsoft.sqlserver:mssql-jdbc")
* [[http://jtds.sourceforge.net/|jTDS JDBC Driver]]
* 주로 MS의 드라이버에 대해 기술함.
* Class : ''com.microsoft.sqlserver.jdbc.SQLServerDriver''
* JDBC Url : ''jdbc:sqlserver://host:port;databaseName=dbname;sendStringParametersAsUnicode=false''
* [[https://docs.microsoft.com/en-us/sql/connect/jdbc/setting-the-connection-properties|Setting the Connection Properties]]
===== Timeout =====
설정값이 millisecond와 second가 섞여 있어서 매우 주의해야 함.
* JDBC Driver 6.1.2 이상 버전부터 올바로 timeout 지원
* [[https://github.com/Microsoft/mssql-jdbc/wiki/QueryTimeout|QueryTimeout · Microsoft/mssql-jdbc Wiki]]
* [[https://github.com/Microsoft/mssql-jdbc/wiki/SocketTimout|SocketTimout · Microsoft/mssql-jdbc Wiki]]
* ''loginTimeout=second'' : connection timeout 역할 **초** 단위
* ''socketTimeout=millisecond'' **밀리초** 단위
* ''queryTimeout=second'' **초** 단위
* ''lockTimeout=millisecond'' : Lock을 기다리는 시간. sessionTimeout, queryTimeout보다는 작은값이어야 할 듯.
===== JDBC Driver 사용시 String 파라미터로인한 Full Scan 문제 =====
* [[https://docs.microsoft.com/ko-kr/sql/t-sql/data-types/data-type-precedence-transact-sql?view=sql-server-2017|데이터 타입 우선순위(Data type precedence]]에 의해 **우선순위가 낮은 타입이 높은 타입으로 형변환 발생**
* 우선순위에 따라 테이블의 컬럼이 ''varchar''이고 파라미터가 ''nvarchar''일 경우에는 우선순위가 낮은 ''varchar'' 타입 컬럼 값을 ''nvarchar''로 일일이 변환해서 값을 비교하기 때문에 성능이 저하되게 됨
* [[http://www.digitalsanctuary.com/tech-blog/java/mssql-jtds-nvarchar-and-slow-indexes.html|MSSQL, jTDS, NVARCHAR and Slow Indexes]]
* [[http://cephas.net/blog/2005/12/02/java-jtds-preparedstatement-and-varchar/|Java, JTDS, PreparedStatement and varchar | Aaron Johnson]]
* [[https://blogs.msdn.microsoft.com/sqlcat/2010/04/05/character-data-type-conversion-when-using-sql-server-jdbc-drivers/|Character data type conversion when using SQL Server JDBC drivers | SQL Server Customer Advisory Team]]
* [[https://vladmihalcea.com/sql-server-jdbc-sendstringparametersasunicode/|SQL Server JDBC - Set sendStringParametersAsUnicode to false]]
# JDBC URL 파라미터로 아래 지정하면 VARCHAR 로 강제로 전송함
sendStringParametersAsUnicode=false
단, 이 경우에도 JDBC 4 에서 지원하는 setNString() 같은 setN* 계열 사용시에는 Unicode로 전송한다.
# sendStringParametersAsUnicode=false 상황에서도 NVARCHAR 전송이 필요하면
pStmt.setObject(2,Id,Types.NVARCHAR); //강제로 Unicode로 전송
# 혹은 setNString() 사용
* ''sendStringParametersAsUnicode=false''로 VARCHAR 전송시에 JDBC Driver가 SQLServer 에 지정된 Collation에 따라서 ''문자열.getBytes(Collation.charset)''으로 byte 배열로 변환하여 전송한다. 완성형의 경우에는 ''CP949''로 변환.
* ''com.microsoft.sqlserver.jdbc.AppDTVImpl.SetValueOp'' 에서 collcation에 따른 charset으로 변환해 보내는 코드 있음.
* 혹은 JDBC 드라이버 변경없이''convert''로 처리한다.
...
WHERE varcharcolumn = convert(varchar, ?) // 굳이 이렇게 안해도 자동으로 됨.
* [[java:hibernate|Hibernate]]에서는 ''@Nationalized'' 사용
@Nationalized
@Column(name = "name", length = 16)
private String name;
* [[java:mybatis|MyBATIS]]는 ''jdbcType=NVARCHAR''사용
SELECT * FROM books WHERE author = #{author} AND title LIKE #{title,jdbcType=NVARCHAR}
===== Logging =====
* MS의 JDBC Driver는 ''java.util.logging'' 사용
* [[java:slf4j|Slf4j]]의 jul-to-slf4j 설정 적용해야 함.
* 쿼리 로그 설정 : 클래스의 패키지 구조와 로거 구조가 일치하지 않음. 또한 JDBC 드라이버 버전마다 로거가 바뀜. 그래서 안나오면 확인필요
* ''com.microsoft.sqlserver'' : ''info'' 이상
* ''com.microsoft.sqlserver.jdbc'' : ''debug''
* [[https://docs.microsoft.com/en-us/sql/connect/jdbc/tracing-driver-operation|Tracing Driver Operation]]
* [[https://blogs.msdn.microsoft.com/psssql/2011/10/16/easy-jdbc-logging/|Easy JDBC Logging – CSS SQL Server Engineers]]
===== Stored Procedure =====
==== Stored Procedure connection catalog와 SP의 catalog가 다를 때 문제 ====
* Stored Procedure 사용시에, JDBC Driver 버그로 인해 현재 접속한 catalog(database)가 아닌 다른 catalog의 Stored Procedure 호출시 오류가 발생한다. [[https://hibernate.atlassian.net/browse/HHH-12704|[HHH-12704] MSSQL executing StoredProcedure on different DB using dot notation throws error - Hibernate JIRA]]
The database name component of the object qualifier must be the name of the current database.
* Spring JDBC Template의 [[https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/simple/SimpleJdbcCall.html|SimpleJdbcCall]] 에서 ''withCatalogName()'', ''withSchemaName()'' 등을 사용해 명시적으로 catalog name을 지정해주면 괜찮다.
* 아마도 JPA 등을 사용시에도 [[https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html#setCatalog-java.lang.String-|Connection.setCatalog()]]를 사용해도 될 것으로 보임. 작업 종료 후 원래 카탈로그로 복구 필요.