【初心者向け/ITスクール33日】JDBCを通してOracleDBMSを利用すする方法
はじめに
今日は、ITスクールに通った33日目の日、今日学んだ知識を記事にシェアしたいと思います。
本記事が、ITを勉強を始めた方々にもロードマップになればいいと思います。
33日目は、JavaでOracle DBMSに繋ぎ、EclipseでQueryを作成する時間を持ちました。
今までは、Oracle DBMSのSQLをSQL Developerを通して、作成しましたが、Eclipseを連携し、
Javaを通してOracle DBMSのデーターを扱うこともできました。
他の言語になっておりますが、これが可能になる理由はJDBCというDriverのおかげです。
JDBC
JDBDとはJava Database Connectivityの略語で、Oracleだけでなく、様々なDBMSをJavaで作成するようにConnectしてくれるAPI Libraryの一種です。そのため、.jar
に存在しており、
普段、Instant Clientを設置する際に、SQL plus、Instant Client Basic、JDBCを一緒にダウンロードし、同じフォルダーで解凍します。
現在、DBMSは400種類もあり、各DBMSによりJDBCの設定方法も少しは違いがありますが、今日はOracleを中心にして紹介したいと思います。
まず、JDBCを利用するためには、対象プロジェクトのBuild pathをクリックし、libraryからinstant client 設置経路にあるojdbc.jarというライブらにを追加します。
まず Connection
というjava.sql packageクラスをインスタンス化します。
それから、コネクトしたいサーバーのアドレスをアドレスを追加します。
下段のData Source Explore -> Oracle Server -> Properties->Driver Properties -> Connection URLからサーバーのURLをコピーし、Stringタイプ変数addressにURLを代入します。
最後に、以下のようにDriverMangerのstatic method getConncetion
を呼び出し、
パラメーターとして、addressとInstant clientに使用したID,PWを入力すれば、
Connectionができます。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class ConnectionMain {
public static void main(String[] args) {
Connection con = null;
try {
String addr = "jdbc:oracle:thin:@localhost:1521:xe";
con = DriverManager.getConnection(addr, "rnjsgurah2", "1234");
System.out.println("Connection Succeed");
}catch(Exception e) {
e.printStackTrace();
}
try {
con.close(); //必ず閉めます。
}catch(SQLException e) {
e.printStackTrace();
}
}
}
これにより、EclipseからJavaでQuery文を作成することができるようになりました。
このアドレスはこれから、繰り返して使いますので、テンプレートとしてクラス化します。
ResultSetというクラスは、後ほど説明します。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class HyonDBManager {
public static Connection connect() throws SQLException{
String addr = "jdbc:oracle:thin:@localhost:1521:xe";
return DriverManager.getConnection(addr, "rnjsgurah2", "1234");
}
public static void close(Connection con, PreparedStatement pstmt, ResultSet rs) {
try {
rs.close();
}catch(Exception e) {
}try {
pstmt.close();
}catch(Exception e) {
}try {
con.close();
}catch(Exception e) {
}
}
}
CRUD
入力
これから、DMLを中心にしてCRUDの自習をやってみましょう。
CRDはほぼ同じロジックにあり、Rのみ前出したResultSetクラスが必要になります。
Connectが成功したという前提から CRDの方法 を説明します!
String sql ="insert into product values(product_seq.nextval,'테스트',10,10,3)";
Queryと同じように作成しますが、空白文字と文字例内に;を付けないことがポイントです!
コードではなく、Scannerを通して場合はどのようにすれば、いいでしょうか?
String name = sc. next
.
.
.
String sql ="insert into product values(product_seq.nextval," + name + ")"
このように、CBVを通して入れてみようとトライしましたが、できませんでした。
Scannerから入力した値を入れるためにはGenericタイプの一種である ワイルドカードタイプパラメータ(?) を活用します。まだ、どのようなタイプが入るかは分からない状況ですが、一度値が入ったらキャストがいらない長所があるタイプがGenericタイプの長所ですね!
String sql ="insert into product values(product_seq.nextval,?)"
処理
先ほど、OracleDBに入れたいQueryを作成し、Stringタイプ変数sqlに代入しました。
それなら、どうやってOracleDBに転送するのでしょうか?
その時は、PreparedStatement(準備された状態)というクラスのオブジェクトを活用します。
そして、PreparedStatementのクラス変数にConnectionのinstance method prepareStatement(String sql)を呼び出せば、準備は完了です。
_PreparedStatement(準備された状態)-> Prepare Statement(準備する)_になりますね!
PreparedStatement pstmt = null;
String sql ="insert into market "
+ "values(market_seq.nextval,"
+ "?,?,?,?)";
pstmt = con.prepareStatement(sql);
もうよい、たん!みたいな待機状態ですが、Updateをする前に
何か忘れたものはありませんか?!
sqlの?を処理する必要がありますね!
pstmt.setString(1, name);
pstmt.setString(2, location);
pstmt.setInt(3, space);
pstmt.setInt(4, park);
?を順番にScannerから代入したデータータイプをセッティングしましょう。
int datacount = pstmt.executeUpdate();
if(datacount==1) {
System.out.println("Success");
}
pstmt.close();
OracleDBにString sqlの値(Query文)入れるためにUpdateをすると、OracleDBに反映されます。
ちなみに、updateはintをリターンしますが、反映されたレコードの数をリターンしますので、計画通りデーターが入ったかもチェックができます!
こちらが、コードになります。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
public class InsertMain2 {
public static void main(String[] args) {
Connection con = null;
//연결
try{
String addr = "jdbc:oracle:thin:@localhost:1521:xe";
con = DriverManager.getConnection(addr,"rnjsgurah2","1234");
//연결이 되면 마켓 정보들 입력 받기
Scanner sc = new Scanner(System.in);
System.out.print("마트 이름 : ");
String name = sc.next();
System.out.print("지점명 : ");
String location = sc.next();
System.out.print("몇 평 : ");
int space = sc.nextInt();
System.out.print("주자 가능 대수 : ");
int park = sc.nextInt();
sc.close();
//SQL => market테이블에 넣을 것
PreparedStatement pstmt = null;
String sql ="insert into market "
+ "values(market_seq.nextval,"
+ "?,?,?,?)";
pstmt =con.prepareStatement(sql);
//?에 값 채우기 : pstmt.setXXX(물음표번호, 값)
// XXX :자료형, 물음표번호는 1부터 시작
pstmt.setString(1, name);
pstmt.setString(2, location);
pstmt.setInt(3, space);
pstmt.setInt(4, park);
//성공 메시지
int datacount = pstmt.executeUpdate();
if(datacount==1) {
System.out.println("Success");
}
pstmt.close();
}catch(Exception e) {
e.printStackTrace();
}
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
UPDATE
mport java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
public class UpdateMain {
//매장명입력 => 그 단어를 포함하는 모든 매장의 상품을 20% 할인된 가격으로 바꾸기
public static void main(String[] args) {
Connection con = null;
PreparedStatement pstmt = null;
try {
//연결
String addr = "jdbc:oracle:thin:@localhost:1521:xe";
con = DriverManager.getConnection(addr,"rnjsgurah2","1234");
System.out.println("success");
//입력
Scanner k = new Scanner(System.in);
System.out.print("매장명: ");
String name = k.next();
k.close();
String sql ="update product set p_price=p_price*0.8 where p_m_no in"
+ "(select m_no from market where m_name like '%'||?||'%')";
//처리
pstmt = con.prepareStatement(sql);
pstmt.setString(1,name);
if(pstmt.executeUpdate()>=1) {
System.out.println("success");
}
}catch(Exception e ) {
e.printStackTrace();
}finally {
try {
pstmt.close();
}catch(SQLException e) {
e.printStackTrace();
}try {
con.close();
}catch(SQLException e) {
e.printStackTrace();
}
}
}//main()end
}//Class end
DELETE
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
public class DeleteMain {
public static void main(String[] args) {
//상품명 입력(Scanner) => 입력한 내용을 포함하는 상품명의 정보를 삭제
Connection con = null;
PreparedStatement pstmt = null;
Scanner sc = new Scanner(System.in);
try {
//연결
String addr = "jdbc:oracle:thin:@localhost:1521:xe";
con = DriverManager.getConnection(addr,"rnjsgurah2","1234");
//입력
System.out.print("상품명 입력 : ");
String name = sc.next();
sc.close();
//문제점 : 여기는 자바의 영역... % 주의!
// %를 문자로 만들어서 문자들을 연결시켜주는 파이프를 사용
String sql = "delete from product "
+ "where p_name like '%'||?||'%'";
pstmt = con.prepareStatement(sql);
pstmt.setString(1,name) ;
//삭제
if(pstmt.executeUpdate()>=1) {
System.out.println("success");
}
}catch(Exception e) {
e.printStackTrace();
}finally{
try {
pstmt.close();
}catch(SQLException e){
e.printStackTrace();
}try {
con.close();
}catch(SQLException e) {
e.printStackTrace();
}
}
}
}
出力
Readも場合、pstmt.executeUpdate()
ではなく、pstmt.executeQuery()を利用します。
前出したexecuteUpdate()
はintタイプをリターンしますが、executeQuery()
はDBからもらった結果をリターンしますので、そのデーターを込めるタイプが必要になります。
そのクラスがResultSetです。
ResultSet rs = null
.
.
re = pstmt.executeQuery();
結果を出力したい場合は、ResultSetクラスのinstance method getXXX("Tableのcolumn name")を呼び出します。注意点として、"Tableのcolumn name"ではなく、indexをキーとして代入することもできますが、readabilityと他の人がコードを見ることまで想定すれば、お勧めはしてないようです。
また、出力はCollectionで勉強したnext()のようにwhile文を通し、empty➡falseになるまでループをします。
while (rs.next()) {
System.out.println(rs.getString(2)); //p_name
System.out.println(rs.getInt("p_weight"));
System.out.println(rs.getInt("p_price"));
System.out.println("---------------");
}
Discussion