programming/java/sem6/lab1/src/app/backend/sqlDriver.java
/**
* Created by Drapegnik on 08.03.17.
*/
package app.backend;
import app.models.*;
import app.config.Options;
import java.sql.*;
import java.text.MessageFormat;
import java.util.*;
/**
* <p>Class for connecting to sql database</p>
*
* @author Ivan Pazhitnykh
* @version 1.0
*/
public class sqlDriver extends dbDriver {
private Connection conn = null;
private Statement stmt = null;
private PreparedStatement pstmt = null;
private ResultSet res = null;
private String sql;
private static String StudentsTable = Student.class.getSimpleName();
private static String MarksTable = Mark.class.getSimpleName();
/**
* SQL requests
*/
private static final String CREATE_STUDENT = MessageFormat.format(
"INSERT INTO {0} (id, s_name, s_group) VALUES(?, ?, ?);", StudentsTable);
private static final String CREATE_MARK = MessageFormat.format(
"INSERT INTO {0} (id, subject, grade, studentId) VALUES(?, ?, ?, ?);", MarksTable);
private static final String GET_STUDENTS = MessageFormat.format(
"SELECT * FROM {0} INNER JOIN {1} ON {1}.studentId={0}.id;", StudentsTable, MarksTable);
private static final String GET_BAD_STUDENTS = MessageFormat.format(
"SELECT {0}.id, {0}.s_name, COUNT(*) as bad_marks_count FROM {0}" +
" INNER JOIN {1} ON {0}.id={1}.studentId" +
" WHERE {1}.grade < 4 GROUP BY {0}.id" +
" HAVING COUNT(*) > 2;", StudentsTable, MarksTable);
private static final String DELETE_STUDENT = MessageFormat.format(
"DELETE st, mrk FROM {0} st" +
" INNER JOIN {1} mrk ON st.id=mrk.studentId" +
" WHERE st.id=?;", StudentsTable, MarksTable);
/**
* Wrapper on {@link sqlDriver#connect()}
*
* @see sqlDriver#connect()
*/
public sqlDriver() {
connect();
}
/**
* Create new database connection
*
* @see Options#JDBC_DRIVER
* @see Options#DB_URL
* @see Options#DB_USER
* @see Options#DB_PASS
*/
private void connect() {
try {
Class.forName(Options.JDBC_DRIVER);
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(Options.DB_URL + Options.DB_NAME, Options.DB_USER, Options.DB_PASS);
stmt = conn.createStatement();
System.out.println("Successfully connect to " + conn.getMetaData().getURL());
} catch (Exception se) {
System.out.println("Some problem with db connection");
se.printStackTrace();
System.exit(1);
}
}
/**
* Create table
*
* @see Options#DB_NAME
*/
private void createTable(String tableName, String sql) {
System.out.println("Creating table...");
try {
stmt.executeUpdate(sql);
System.out.println("Table '" + Options.DB_NAME + "." + tableName + "' created successfully.");
} catch (Exception se) {
se.printStackTrace();
}
}
/**
* Create {@link Student}s table
*
* @see sqlDriver#createTable(String, String)
* @see Options#DB_NAME
*/
private void createStudentsTable() {
String sql = "CREATE TABLE " + StudentsTable +
"(id VARCHAR(255) not NULL, " +
" s_name VARCHAR(255), " +
" s_group INTEGER, " +
" PRIMARY KEY ( id ))";
createTable(Student.class.getSimpleName(), sql);
}
/**
* Create {@link Mark}s table
*
* @see sqlDriver#createTable(String, String)
* @see Options#DB_NAME
*/
private void createMarkTable() {
String sql = "CREATE TABLE " + MarksTable +
"(id VARCHAR(255) not NULL, " +
" subject VARCHAR(255), " +
" grade INTEGER, " +
" studentId VARCHAR(255) not NULL, " +
" PRIMARY KEY ( id ))";
createTable(Mark.class.getSimpleName(), sql);
}
/**
* Drop database if exist, and create new
*
* @see Options#DB_NAME
*/
private void dropDB() {
try {
System.out.println("Drop database...");
sql = "DROP DATABASE IF EXISTS " + Options.DB_NAME;
stmt.executeUpdate(sql);
System.out.println("Creating database...");
sql = "CREATE DATABASE " + Options.DB_NAME;
stmt.executeUpdate(sql);
System.out.println("Database '" + Options.DB_NAME + "' created successfully.");
} catch (Exception se) {
se.printStackTrace();
}
}
/**
* Insert {@link Student} object into table
*
* @param student {@link Student} instance
*/
@Override
public void createStudent(Student student) {
try {
pstmt = conn.prepareStatement(CREATE_STUDENT);
pstmt.setString(1, student.getId());
pstmt.setString(2, student.getName());
pstmt.setInt(3, student.getGroup());
pstmt.executeUpdate();
} catch (Exception se) {
se.printStackTrace();
}
}
/**
* Remove {@link Student} and all his {@link Mark}s from db
*
* @param id {@link Student#id}
*/
@Override
public void deleteStudent(String id) {
try {
System.out.println("Delete student...");
pstmt = conn.prepareStatement(DELETE_STUDENT);
pstmt.setString(1, id);
pstmt.executeUpdate();
System.out.println("Successfully delete student with id=" + id);
} catch (Exception se) {
se.printStackTrace();
}
}
/**
* Select all {@link Student}'s objects from db
*
* @return <pre>{@code ArrayList<Student>}</pre> {@link Student}'s objects
*/
@Override
public ArrayList<Student> getStudents() {
System.out.println("Select students...");
ArrayList<Student> data = new ArrayList<>();
try {
res = stmt.executeQuery(GET_STUDENTS);
HashMap<String, Student> map = new HashMap<>();
while (res.next()) {
String id = res.getString("id");
Student st = map.get(id);
if (st == null) {
st = new Student(id, res.getString("s_name"), Integer.parseInt(res.getString("s_group")));
}
st.addMark(new Mark(res.getString("subject"), Integer.parseInt(res.getString("grade")), id));
map.put(id, st);
if (Options.DEBUG) {
System.out.println("\t#" + res.getRow()
+ "\t" + res.getString("s_name")
+ "\t" + res.getString("subject")
+ "\t" + res.getString("grade")
+ "\t" + res.getString("id"));
}
}
for (Map.Entry<String, Student> entry : map.entrySet()) {
Student st = entry.getValue();
data.add(st);
if (Options.DEBUG) {
System.out.println(st);
}
}
System.out.println("Successfully select " + data.size() + " students.");
} catch (Exception se) {
se.printStackTrace();
}
return data;
}
/**
* Select all {@link Student}'s objects from db
* that have 3 and more bad (1, 2, 3) marks
*
* @return <pre>{@code ArrayList<String>} students_ids</pre>
*/
@Override
public ArrayList<String> getBadStudentsIds() {
System.out.println("Select bad students...");
ArrayList<String> data = new ArrayList<>();
try {
res = stmt.executeQuery(GET_BAD_STUDENTS);
while (res.next()) {
data.add(res.getString("id"));
if (Options.DEBUG) {
System.out.println("\t#" + res.getRow()
+ "\t" + res.getString("s_name")
+ "\t" + res.getString("bad_marks_count")
+ "\t" + res.getString("id"));
}
}
System.out.println("Successfully select " + data.size() + " bad students.");
} catch (Exception se) {
se.printStackTrace();
}
return data;
}
/**
* Insert {@link Mark} object into table
*
* @param mark {@link Mark} instance
*/
@Override
public void createMark(Mark mark) {
try {
stmt = conn.createStatement();
pstmt = conn.prepareStatement(CREATE_MARK);
pstmt.setString(1, mark.getId());
pstmt.setString(2, mark.getSubject().toString());
pstmt.setInt(3, mark.getGrade());
pstmt.setString(4, mark.getStudentId());
pstmt.executeUpdate();
} catch (Exception se) {
se.printStackTrace();
}
}
/**
* Fetch {@link Student}s data from {@link Options#STUDENTS_FILE_NAME}
* Generate random {@link Mark}s with {@link Subject}s
* Save all data into db
*
* @see sqlDriver#createMark(Mark)
* @see sqlDriver#createStudent(Student)
* @see Options#STUDENTS_FILE_NAME
*/
private void initDB() {
System.out.println("Init database...");
ArrayList<Student> data = Student.readFromFile(Options.STUDENTS_FILE_NAME);
Random random = new Random();
for (Student student : data) {
System.out.println('\t' + student.shortToString());
createStudent(student);
for (Subject subject : Subject.values()) {
Mark mark = new Mark(subject, random.nextInt(10) + 1, student.getId());
System.out.println('\t' + mark.toString());
createMark(mark);
}
System.out.println();
}
}
private void dumpStudentsIntoFile() {
Student.writeInFile(Options.STUDENTS_FILE_NAME, getStudents());
}
/**
* Drop database if exist, and create new
* Create all tables
*
* @see sqlDriver#dropDB()
* @see sqlDriver#createStudentsTable()
* @see sqlDriver#createMarkTable()
* @see Options#DB_NAME
*/
private void createDB() {
dropDB();
connect();
createStudentsTable();
createMarkTable();
}
private void close() {
try {
if (stmt != null)
stmt.close();
} catch (SQLException se2) {
System.out.println(se2.getMessage());
}
try {
if (pstmt != null)
pstmt.close();
} catch (SQLException se2) {
System.out.println(se2.getMessage());
}
try {
if (conn != null)
conn.close();
} catch (SQLException se) {
se.printStackTrace();
}
System.out.println("Close db connection... Goodbye!");
}
public static void main(String[] args) {
sqlDriver db = new sqlDriver();
db.createDB();
db.initDB();
db.getStudents();
db.close();
// Student.writeInFile(app.config.Options.STUDENTS_FILE_NAME, Student.generateFakeData());
}
}