원본출처: 티스토리 바로가기
오늘은 구현하고자 하는 앱에서 MSSQL 등의 DB 서버 접속에 대한 이야기를 해 볼까 합니다. java에서 JDBC 등으로 DB Server 접속하는 web 서비스 구현을 해 보기는 했습니다만. android에서 jdbc 등으로 DB 접속을 구현해 보는 건 또 처음인 듯합니다.
일반적으로 앱 서비스를 구현하더라도 DB 서버에 직접 접속하는 것은 그렇게 바람직한 모습은 아닌 것으로 생각이 듭니다. 그래도 한번 구현을 도전해 보겠습니다.
// MSSQL jdbc connect implementation 'net.sourceforge.jtds:jtds:1.3.1' // coroutines & lifecycle 처리를 위해서 2줄 추가 implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3' implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.2"
JDBC 을 접속하는 jtsd 라이브러리를 imlementation 했습니다. lifecycle 과 관련된 라이브러리는 안드로이드 앱이라는 제한성 때문에 비동기 처리를 해야 했기 때문에 추가했습니다.
firebase 등의 API 가 지원되는 경우에는 API 가 비동기 통신을 지원하기 때문에 그냥 코드 작업을 진행할 수 있었지만, 이 프로젝트의 경우는 그 부분에 제한이 있었습니다.
<uses-permission android:name="android.permission.INTERNET"/>
manifest 에 internet 사용을 위한 권한 허가를 설정했습니다. 우리가 사용하는 안드로이드 단말기는 WIFI 나 통신사의 통신망을 활용해서 외부와 통신을 해야 하기 때문에 기본적으로 넣어 두어야 합니다.
이제 DB 와 통신을 하기 위한 Connecter을 구현해 보겠습니다.
import android.os.StrictMode import android.util.Log import android.widget.EditText import java.sql.Connection import java.sql.DriverManager import java.sql.SQLException class MsConnection { private val ip="서버IP:서버port" private val db="database name" private val username="username" private val password="password" fun dbConn():Connection? { val policy=StrictMode.ThreadPolicy.Builder().permitAll().build() StrictMode.setThreadPolicy(policy) var conn:Connection?=null var connString:String?=null try { Class.forName("net.sourceforge.jtds.jdbc.Driver") connString="jdbc:jtds:sqlserver://$ip;databaseName=$db;user=$username;password=$password" conn=DriverManager.getConnection(connString) } catch (ex:SQLException) { Log.e("Error1 : ", "error ${ex.localizedMessage}") } catch (ex1:ClassNotFoundException) { Log.e("Error2 : ", "error ${ex1.localizedMessage}") } catch (ex2:Exception) { Log.e("Error3 : ", "error ${ex2.localizedMessage}") } return conn } }
mssql의 경우는 connection string을 jdbc:jtds:sqlserver... 이렇게 작성하는 것으로 확인이 되었습니다. oracle 이라면 jdbc:oracle:thin... 이런 식으로 작성을 하게 됩니다.
다른 DB 서버와 접속을 하게 되더라도 비슷한 구조를 가지게 되지 않을 까 하는 생각이 듭니다.
fun doGetData() { val dbConn = MsConnection().dbConn() if (dbConn == null) { Toast.makeText(context, context.getString(R.string.msgDontDBconn), Toast.LENGTH_SHORT).show() return } viewModelScope.launch { val sp = context.getSharedPreferences(context.packageName, Context.MODE_PRIVATE) val userDiv = sp.getString("userdiv", "0") val compDiv = sp.getString("comp_div", "") val location = sp.getString("location", "") var query = "select * from table_name where cnt > 0" Log.e("", "query =$query") val statement = dbConn.createStatement() val rs = statement.executeQuery(query) prods.clear() while(rs.next()) { val prodBean = Prod100Bean( rs.getInt("seq"), rs.getString("id"), rs.getInt("cnt"), ) Log.e("", "seq = ${prod100Bean.seq}") prods.add(prod100Bean) } prods.sortByDescending { it.seq } dbConn.close() } }
데이터를 읽어오는 코드는 이런 예제와 같이 구현이 될 수 있을 듯 합니다. 위 예제 코드는 viewModel에 들어 있는 fun 이기 때문에 viewModelScope.launch { }을 이용해서 thread 처리를 했습니다. 그렇게 비동기 처리를 하지 않는 경우 androi d는 오류를 표시하게 됩니다.
이런 정도로 그 구현에 대해서 알아 보았습니다. 다음에도 이런 작업은 이제 수월하게 진행할 수 있을 것 같습니다.
댓글
댓글 쓰기