Skip to content

Instantly share code, notes, and snippets.

@Brutt
Created March 21, 2018 06:18
Show Gist options
  • Save Brutt/eb051356917294f9caa76cab8a059132 to your computer and use it in GitHub Desktop.
Save Brutt/eb051356917294f9caa76cab8a059132 to your computer and use it in GitHub Desktop.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Column {
String name();
int primary() default 0;
int updatable() default 0;
}
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Dao {
private static String getTableName(Class clazz){
if (!clazz.isAnnotationPresent(Table.class)) {
throw new IllegalArgumentException("Annotation @Table is not present");
}
Table annotation = (Table) clazz.getAnnotation(Table.class);
return annotation.name().isEmpty() ? clazz.getName() : annotation.name();
}
static String save(Object obj) throws Exception {
StringBuilder query = new StringBuilder("INSERT INTO ");
Class clazz = obj.getClass();
// add table name to query
String tableName = getTableName(clazz);
query.append(tableName);
query.append(" (");
// collect column names and values of corresponding fields
List<String> columnNames = new ArrayList<>();
List<Object> valuesToInsert = new ArrayList<>();
for (Field field : clazz.getDeclaredFields()) {
Column columnAnnotation = field.getAnnotation(Column.class);
if (columnAnnotation != null) {
// get column name
String columnName = columnAnnotation.name().isEmpty() ?
field.getName() : columnAnnotation.name();
columnNames.add(columnName);
// get value for this column
field.setAccessible(true);
Object columnValue = field.get(obj);
valuesToInsert.add(columnValue);
field.setAccessible(false);
}
}
// just for info (DON'T USE SUCH TECHNIQUE FOR DEBUG PURPOSES!!!)
printColumnNamesAndValues(columnNames, valuesToInsert);
// generate rest of query
appendColumnNames(query, columnNames);
query.append(")");
appendColumnValues(query, valuesToInsert);
return query.toString();
}
private static void printColumnNamesAndValues(List<String> columnNames, List<Object> valuesToInsert) {
System.out.println("Column names and values list:");
Iterator<String> namesIterator = columnNames.iterator();
Iterator<Object> valuesIterator = valuesToInsert.iterator();
while (namesIterator.hasNext()) {
System.out.println(namesIterator.next() + " -> " + valuesIterator.next());
}
}
private static void appendColumnNames(StringBuilder query, List<String> columnNames) {
for (String columnName : columnNames) {
query.append(columnName);
query.append(", ");
}
// remove last ", "
query.setLength(query.length() - 2);
}
private static void appendColumnValues(StringBuilder query, List<?> columnValues) {
query.append(" VALUES (");
for (Object columnValue : columnValues) {
query.append(columnValue);
query.append(", ");
}
// remove last ", "
query.setLength(query.length() - 2);
query.append(");");
}
// TODO: Generate SQL to get all instances of clazz from DB
public static String getAll(Class clazz) {
StringBuilder query = new StringBuilder("SELECT ");
String tableName = getTableName(clazz);
// collect column names and values of corresponding fields
List<String> columnNames = new ArrayList<>();
List<Object> valuesToInsert = new ArrayList<>();
for (Field field : clazz.getDeclaredFields()) {
Column columnAnnotation = field.getAnnotation(Column.class);
if (columnAnnotation != null) {
// get column name
String columnName = columnAnnotation.name().isEmpty() ?
field.getName() : columnAnnotation.name();
columnNames.add(columnName);
}
}
// generate rest of query
appendColumnNames(query, columnNames);
query.append(" FROM ");
query.append(tableName);
query.append(";");
// just for info (DON'T USE SUCH TECHNIQUE FOR DEBUG PURPOSES!!!)
//printColumnNamesAndValues(columnNames, valuesToInsert);
return query.toString();
}
// TODO: Generate SQL which can remove Object of clazz by it's id
// Hint: you will probably need to indicate somehow that current @Column is primary key in table
public static String deleteById(Object id, Class clazz) {
StringBuilder query = new StringBuilder("DELETE FROM ");
String tableName = getTableName(clazz);
query.append(tableName);
query.append(" WHERE ");
for (Field field : clazz.getDeclaredFields()) {
Column columnAnnotation = field.getAnnotation(Column.class);
if ((columnAnnotation != null) && (columnAnnotation.primary() == 1)) {
query.append(columnAnnotation.name());
query.append(" = ").append(id).append(";");
break;
}
}
return query.toString();
}
// TODO: Generate SQL which can Update Object representation in DB
public static String updateSalaryForIdByRate(Class clazz, int id, int rate) {
StringBuilder query = new StringBuilder("UPDATE ");
String tableName = getTableName(clazz);
query.append(tableName);
query.append(" SET ");
String strId = "";
String strSalary = "";
for (Field field : clazz.getDeclaredFields()) {
Column columnAnnotation = field.getAnnotation(Column.class);
if (columnAnnotation != null) {
if (columnAnnotation.primary() == 1) {
strId = columnAnnotation.name();
}
if (columnAnnotation.updatable() == 1) {
strSalary = columnAnnotation.name();
}
}
}
query.append(strSalary).append(" = ").append(strSalary).append(" * ").append(rate).append(" WHERE ").append(strId).append(" = ").append(id).append(";");
return query.toString();
}
}
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class DaoTest {
@Test
public void testSave() throws Exception {
User user = new User(1, "Tolik", 100.0d);
String expectedQuery = "INSERT INTO dan_user (id, name, sal) VALUES (1, Tolik, 100.0);";
String actualQuery = Dao.save(user);
assertEquals(expectedQuery, actualQuery);
}
@Test
public void testGetAll() throws Exception {
String expectedQuery = "SELECT id, name, sal FROM dan_user;";
String actualQuery = Dao.getAll(User.class);
assertEquals(expectedQuery, actualQuery);
}
@Test
public void testDeleteById() throws Exception {
String expectedQuery = "DELETE FROM dan_user WHERE id = 1;";
String actualQuery = Dao.deleteById(1, User.class);
assertEquals(expectedQuery, actualQuery);
}
@Test
public void testUpdate() throws Exception {
String expectedQuery = "UPDATE dan_user SET sal = sal * 2 WHERE id = 1;";
String actualQuery = Dao.updateSalaryForIdByRate(User.class, 1, 2);
assertEquals(expectedQuery, actualQuery);
}
}
@Table(name="dan_user")
public class User {
@Column(name="id", primary = 1)
private int id;
@Column(name="name")
private String name;
@Column(name="sal", updatable = 1)
private double salary;
public User(int id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment