昨日は1日で1つのホイール、もう1つのOR mappingを繰り返し作りました.
34847 ワード
もう一つannotationを使ったormの実現は、とてもつまらないものです.
しかし、実現の過程で、考えてみると、selectから出発するormは非常に使いにくいと感じます.どんなに簡単なシステムでも、select文には複雑な内外接続、パケットなどのクエリーロジックが表示されます.
しかし、データ記憶部、すなわちupate、insert、delete部では、論理が非常に簡単であり、ormを使用すると良い効果が得られることが多い.
そして、DAOモードについて考えてみると、通常理解されているDAOモードでは、データの読み取りと書き込みは同じDAOクラスに置かれており、実際の開発ではselect関連のfindXXXメソッドが良いgetXXXXメソッドが非常に多いのですが、update、insert、add、saveなどのメソッドの個数が少なく、個人的にはDAOやデータアクセス層プログラムを開発する場合、DAOは書き込みDAOと読み取りDAOに分けられると同時に、ここで読み書き分離を実現し、1つのライブラリに書き込み、複数のライブラリを読み取り、バッファプールを読み取り、書き込み直接書き込みを行い、データベースメカニズムテーブルの同期を利用して、システムの伸縮性を高めることを考慮することができる.
また@1兄の答えによると、書き込み操作自体は非常に遅い動作であり、書き込み時に反射を加え、象の体のダニのように、ディスクに比べて反射の消費は無視できるはずだ.
そして、ついでにNutzDAOに対して小さな批判を行い、DAOミドルウェアとして、いくつかのことをしすぎて、かえってあまりよくありません.例えば、いわゆるwhereClauseの条件検索を導入して、実際の業務の中のselectのSQLは非常に複雑で、簡単な条件でパッケージ化して、実際の開発の需要を満たすのは難しいです.
hibernateも最初は使いやすいことを知っておく必要がありますが、直面している需要が多く、境界がはっきりしていないと、コードが冗長になって、だんだん使えなくなります.
次のキーコードを貼ります.
Insert関連クラス:
//////////////////////
反射ツールクラス:
表の列で処理されるエンティティ・オブジェクト
サポートタイプの列挙
次はいくつかのannotationの定義です
次に、実装クラスを変更および削除します.
削除:
最終的なDAO実装:
最後にTransactionの実装を補足します.ここでは実装方法がたくさんあります.ここで与えられたTransactionはその1つにすぎません.
最後に、改めて@1兄さんに感謝
しかし、実現の過程で、考えてみると、selectから出発するormは非常に使いにくいと感じます.どんなに簡単なシステムでも、select文には複雑な内外接続、パケットなどのクエリーロジックが表示されます.
しかし、データ記憶部、すなわちupate、insert、delete部では、論理が非常に簡単であり、ormを使用すると良い効果が得られることが多い.
そして、DAOモードについて考えてみると、通常理解されているDAOモードでは、データの読み取りと書き込みは同じDAOクラスに置かれており、実際の開発ではselect関連のfindXXXメソッドが良いgetXXXXメソッドが非常に多いのですが、update、insert、add、saveなどのメソッドの個数が少なく、個人的にはDAOやデータアクセス層プログラムを開発する場合、DAOは書き込みDAOと読み取りDAOに分けられると同時に、ここで読み書き分離を実現し、1つのライブラリに書き込み、複数のライブラリを読み取り、バッファプールを読み取り、書き込み直接書き込みを行い、データベースメカニズムテーブルの同期を利用して、システムの伸縮性を高めることを考慮することができる.
また@1兄の答えによると、書き込み操作自体は非常に遅い動作であり、書き込み時に反射を加え、象の体のダニのように、ディスクに比べて反射の消費は無視できるはずだ.
そして、ついでにNutzDAOに対して小さな批判を行い、DAOミドルウェアとして、いくつかのことをしすぎて、かえってあまりよくありません.例えば、いわゆるwhereClauseの条件検索を導入して、実際の業務の中のselectのSQLは非常に複雑で、簡単な条件でパッケージ化して、実際の開発の需要を満たすのは難しいです.
hibernateも最初は使いやすいことを知っておく必要がありますが、直面している需要が多く、境界がはっきりしていないと、コードが冗長になって、だんだん使えなくなります.
次のキーコードを貼ります.
Insert関連クラス:
//////////////////////
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.kamike.db.generic;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
/**
*
* @author THiNk
* @param <T>
*/
public class GenericInsert<T> {
protected T t;
protected ArrayList<GenericColumn> columns;
protected HashMap<String, Object> data;
protected ArrayList<Field> fields;
protected String tableName;
public GenericInsert(T t) {
this.t = t;
tableName = t.getClass().getAnnotation(TableName.class).value();
Field[] fs = t.getClass().getDeclaredFields();
columns = new ArrayList<>();
for (Field field : fs) {
FieldName fieldName = field.getAnnotation(FieldName.class);
if (fieldName != null) {
String fname;
if ("".equals(fieldName.value())) {
fname = field.getName();
} else {
fname = fieldName.value();
}
GenericColumn col = new GenericColumn();
col.setName(fname);
col.setField(field);
if (field.getType() == int.class) {
col.setType(GenericType.Int);
col.setIntValue(GenericReflect.getInt(field, t));
columns.add(col);
} else if (field.getType() == int.class) {
col.setType(GenericType.Double);
col.setDoubleValue(GenericReflect.getDouble(field, t));
columns.add(col);
} else if (field.getType() == String.class) {
col.setType(GenericType.String);
col.setStrValue(GenericReflect.getString(field, t));
columns.add(col);
} else if (field.getType() == long.class) {
col.setType(GenericType.Long);
col.setLongValue(GenericReflect.getLong(field, t));
columns.add(col);
} else if (field.getType() == Date.class) {
col.setType(GenericType.Timestamp);
col.setTimestampValue(new Timestamp(GenericReflect.getDate(field, t).getTime()));
columns.add(col);
} else if (field.getType() == boolean.class) {
col.setType(GenericType.Boolean);
col.setBooleanValue(GenericReflect.getBoolean(field, t));
columns.add(col);
}
}
}
}
public String sql() {
StringBuffer buffer = new StringBuffer();
buffer.append("insert into ");
buffer.append(tableName);
buffer.append("( ");
StringBuffer values = new StringBuffer();
for (Iterator<GenericColumn> it = columns.iterator(); it.hasNext();) {
GenericColumn column = it.next();
buffer.append(column.getName());
values.append("?");
if (it.hasNext()) {
buffer.append(",");
values.append(",");
}
}
buffer.append(")");
buffer.append(" values(");
buffer.append(values);
buffer.append(") ");
return buffer.toString();
}
public int bind(PreparedStatement ps) throws SQLException {
if (ps == null) {
return 0;
}
int i = 1;
for (Iterator<GenericColumn> it = columns.iterator(); it.hasNext();) {
GenericColumn column = it.next();
switch (column.getType()) {
case Int:
ps.setInt(i, column.getIntValue());
break;
case Long:
ps.setLong(i, column.getLongValue());
break;
case Double:
ps.setDouble(i, column.getDoubleValue());
break;
case Boolean:
ps.setBoolean(i, column.getBooleanValue());
break;
case Timestamp:
ps.setTimestamp(i, column.getTimestampValue());
break;
case String:
ps.setString(i, column.getStrValue());
break;
}
i++;
}
return i;
}
}
反射ツールクラス:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.kamike.db.generic;
import java.lang.reflect.Field;
import java.util.Date;
/**
*
* @author THiNk
*/
public class GenericReflect {
public static Object get(Field field, Object obj) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
return null == obj ? null : field.get(obj);
} catch (Exception e) {
return null;
}
}
public static String getString(Field field, Object obj) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
return null == obj ? null : (String) field.get(obj);
} catch (Exception e) {
return null;
}
}
public static int getInt(Field field, Object obj) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
return null == obj ? null : (int) field.get(obj);
} catch (Exception e) {
return 0;
}
}
public static double getDouble(Field field, Object obj) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
return null == obj ? null : (double) field.get(obj);
} catch (Exception e) {
return 0d;
}
}
public static long getLong(Field field, Object obj) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
return null == obj ? null : (long) field.get(obj);
} catch (Exception e) {
return 0l;
}
}
public static Date getDate(Field field, Object obj) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
return null == obj ? null : (Date) field.get(obj);
} catch (Exception e) {
return new Date(System.currentTimeMillis());
}
}
public static boolean getBoolean(Field field, Object obj) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
return null == obj ? null : (boolean) field.get(obj);
} catch (Exception e) {
return false;
}
}
public static void set(Object obj, Field field, String value) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(obj, value);
} catch (Exception e) {
}
}
public static void set(Object obj, Field field, int value) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(obj, value);
} catch (Exception e) {
}
}
public static void set(Object obj, Field field, boolean value) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(obj, value);
} catch (Exception e) {
}
}
public static void set(Object obj, Field field, Date value) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(obj, value);
} catch (Exception e) {
}
}
public static void set(Object obj, Field field, long value) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(obj, value);
} catch (Exception e) {
}
}
public static void set(Object obj, Field field, double value) {
try {
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(obj, value);
} catch (Exception e) {
}
}
}
表の列で処理されるエンティティ・オブジェクト
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.kamike.db.generic;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.util.Date;
/**
*
* @author THiNk
*/
public class GenericColumn {
private String name;
private GenericType type;
private Field field;
private Object value;
private String strValue;
private int intValue;
private double doubleValue;
private Timestamp timestampValue;
private long longValue;
private boolean booleanValue;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the type
*/
public GenericType getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(GenericType type) {
this.type = type;
}
/**
* @return the field
*/
public Field getField() {
return field;
}
/**
* @param field the field to set
*/
public void setField(Field field) {
this.field = field;
}
/**
* @return the value
*/
public Object getValue() {
return value;
}
/**
* @param value the value to set
*/
public void setValue(Object value) {
this.value = value;
}
/**
* @return the strValue
*/
public String getStrValue() {
return strValue;
}
/**
* @param strValue the strValue to set
*/
public void setStrValue(String strValue) {
this.strValue = strValue;
}
/**
* @return the intValue
*/
public int getIntValue() {
return intValue;
}
/**
* @param intValue the intValue to set
*/
public void setIntValue(int intValue) {
this.intValue = intValue;
}
/**
* @return the doubleValue
*/
public double getDoubleValue() {
return doubleValue;
}
/**
* @param doubleValue the doubleValue to set
*/
public void setDoubleValue(double doubleValue) {
this.doubleValue = doubleValue;
}
/**
* @return the timestampValue
*/
public Timestamp getTimestampValue() {
return timestampValue;
}
/**
* @param timestampValue the timestampValue to set
*/
public void setTimestampValue(Timestamp timestampValue) {
this.timestampValue = timestampValue;
}
/**
* @return the longValue
*/
public long getLongValue() {
return longValue;
}
/**
* @param longValue the longValue to set
*/
public void setLongValue(long longValue) {
this.longValue = longValue;
}
/**
* @return the booleanValue
*/
public boolean getBooleanValue() {
return booleanValue;
}
/**
* @param booleanValue the booleanValue to set
*/
public void setBooleanValue(boolean booleanValue) {
this.booleanValue = booleanValue;
}
}
サポートタイプの列挙
package com.kamike.db.generic;
/**
*
* @author THiNk
*/
public enum GenericType {
String,
Int,
Long,
Boolean,
Double,
Timestamp
}
次はいくつかのannotationの定義です
package com.kamike.db.generic;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author THiNk
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
public @interface Id {
String value() default "id";
}
package com.kamike.db.generic;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* @author THiNk
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldName {
String value() default "";
}package com.kamike.db.generic;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableName {
String value() default "";
}
次に、実装クラスを変更および削除します.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.kamike.db.generic;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
/**
*
* @author THiNk
* @param <T>
*/
public class GenericUpdate<T> {
protected T t;
protected ArrayList<GenericColumn> columns;
protected ArrayList<GenericColumn> ids;
protected String tableName;
public GenericUpdate(T t) {
this.t = t;
tableName = t.getClass().getAnnotation(TableName.class).value();
Field[] fs = t.getClass().getDeclaredFields();
columns = new ArrayList<>();
for (Field field : fs) {
FieldName fieldName = field.getAnnotation(FieldName.class);
if (fieldName != null) {
String fname;
if ("".equals(fieldName.value())) {
fname = field.getName();
} else {
fname = fieldName.value();
}
GenericColumn col = new GenericColumn();
col.setName(fname);
col.setField(field);
if (field.getType() == int.class) {
col.setType(GenericType.Int);
col.setIntValue(GenericReflect.getInt(field, t));
columns.add(col);
Id id = field.getAnnotation(Id.class);
if (id != null) {
ids.add(col);
}
} else if (field.getType() == int.class) {
col.setType(GenericType.Double);
col.setDoubleValue(GenericReflect.getDouble(field, t));
columns.add(col);
Id id = field.getAnnotation(Id.class);
if (id != null) {
ids.add(col);
}
} else if (field.getType() == String.class) {
col.setType(GenericType.String);
col.setStrValue(GenericReflect.getString(field, t));
columns.add(col);
Id id = field.getAnnotation(Id.class);
if (id != null) {
ids.add(col);
}
} else if (field.getType() == long.class) {
col.setType(GenericType.Long);
col.setLongValue(GenericReflect.getLong(field, t));
columns.add(col);
Id id = field.getAnnotation(Id.class);
if (id != null) {
ids.add(col);
}
} else if (field.getType() == Date.class) {
col.setType(GenericType.Timestamp);
col.setTimestampValue(new Timestamp(GenericReflect.getDate(field, t).getTime()));
columns.add(col);
Id id = field.getAnnotation(Id.class);
if (id != null) {
ids.add(col);
}
} else if (field.getType() == boolean.class) {
col.setType(GenericType.Boolean);
col.setBooleanValue(GenericReflect.getBoolean(field, t));
columns.add(col);
Id id = field.getAnnotation(Id.class);
if (id != null) {
ids.add(col);
}
}
}
}
}
public String sql() {
StringBuffer buffer = new StringBuffer();
buffer.append("update ");
buffer.append(tableName);
buffer.append(" set ");
for (Iterator<GenericColumn> it = columns.iterator(); it.hasNext();) {
GenericColumn column = it.next();
buffer.append(column.getName());
buffer.append("=?");
if (it.hasNext()) {
buffer.append(", ");
}
}
buffer.append(" where ");
for (Iterator<GenericColumn> it = ids.iterator(); it.hasNext();) {
GenericColumn column = it.next();
buffer.append(column.getName());
buffer.append("=? ");
if (it.hasNext()) {
buffer.append(" and ");
}
}
return buffer.toString();
}
public String rawSql() {
StringBuffer buffer = new StringBuffer();
buffer.append("update ");
buffer.append(tableName);
buffer.append(" set ");
for (Iterator<GenericColumn> it = columns.iterator(); it.hasNext();) {
GenericColumn column = it.next();
buffer.append(column.getName());
buffer.append("=?");
if (it.hasNext()) {
buffer.append(", ");
}
}
return buffer.toString();
}
public int bind(PreparedStatement ps) throws SQLException {
if (ps == null) {
return 0;
}
int i = 1;
for (Iterator<GenericColumn> it = columns.iterator(); it.hasNext();) {
GenericColumn column = it.next();
switch (column.getType()) {
case Int:
ps.setInt(i, column.getIntValue());
break;
case Long:
ps.setLong(i, column.getLongValue());
break;
case Double:
ps.setDouble(i, column.getDoubleValue());
break;
case Boolean:
ps.setBoolean(i, column.getBooleanValue());
break;
case Timestamp:
ps.setTimestamp(i, column.getTimestampValue());
break;
case String:
ps.setString(i, column.getStrValue());
break;
}
i++;
}
for (Iterator<GenericColumn> it = ids.iterator(); it.hasNext();) {
GenericColumn column = it.next();
switch (column.getType()) {
case Int:
ps.setInt(i, column.getIntValue());
break;
case Long:
ps.setLong(i, column.getLongValue());
break;
case Double:
ps.setDouble(i, column.getDoubleValue());
break;
case Boolean:
ps.setBoolean(i, column.getBooleanValue());
break;
case Timestamp:
ps.setTimestamp(i, column.getTimestampValue());
break;
case String:
ps.setString(i, column.getStrValue());
break;
}
i++;
}
return i;
}
public int rawBind (PreparedStatement ps) throws SQLException {
if (ps == null) {
return 0;
}
int i = 1;
for (Iterator<GenericColumn> it = columns.iterator(); it.hasNext();) {
GenericColumn column = it.next();
switch (column.getType()) {
case Int:
ps.setInt(i, column.getIntValue());
break;
case Long:
ps.setLong(i, column.getLongValue());
break;
case Double:
ps.setDouble(i, column.getDoubleValue());
break;
case Boolean:
ps.setBoolean(i, column.getBooleanValue());
break;
case Timestamp:
ps.setTimestamp(i, column.getTimestampValue());
break;
case String:
ps.setString(i, column.getStrValue());
break;
}
i++;
}
return i;
}
}
削除:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.kamike.db.generic;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
/**
*
* @author THiNk
* @param <T>
*/
public class GenericDelete<T> {
protected T t;
protected ArrayList<GenericColumn> ids;
protected String tableName;
public GenericDelete(T t) {
this.t = t;
tableName = t.getClass().getAnnotation(TableName.class).value();
Field[] fs = t.getClass().getDeclaredFields();
ids = new ArrayList<>();
for (Field field : fs) {
FieldName fieldName = field.getAnnotation(FieldName.class);
if (fieldName != null) {
String fname;
if ("".equals(fieldName.value())) {
fname = field.getName();
} else {
fname = fieldName.value();
}
GenericColumn col = new GenericColumn();
col.setName(fname);
col.setField(field);
if (field.getType() == int.class) {
col.setType(GenericType.Int);
col.setIntValue(GenericReflect.getInt(field, t));
ids.add(col);
} else if (field.getType() == int.class) {
col.setType(GenericType.Double);
col.setDoubleValue(GenericReflect.getDouble(field, t));
ids.add(col);
} else if (field.getType() == String.class) {
col.setType(GenericType.String);
col.setStrValue(GenericReflect.getString(field, t));
ids.add(col);
} else if (field.getType() == long.class) {
col.setType(GenericType.Long);
col.setLongValue(GenericReflect.getLong(field, t));
ids.add(col);
} else if (field.getType() == Date.class) {
col.setType(GenericType.Timestamp);
col.setTimestampValue(new Timestamp(GenericReflect.getDate(field, t).getTime()));
ids.add(col);
} else if (field.getType() == boolean.class) {
col.setType(GenericType.Boolean);
col.setBooleanValue(GenericReflect.getBoolean(field, t));
ids.add(col);
}
}
}
}
public String sql() {
StringBuffer buffer = new StringBuffer();
buffer.append("delete from ");
buffer.append(tableName);
buffer.append(" where ");
for (Iterator<GenericColumn> it = ids.iterator(); it.hasNext();) {
GenericColumn id = it.next();
buffer.append(id.getName());
buffer.append("=? ");
if (it.hasNext()) {
buffer.append(" and ");
}
}
return buffer.toString();
}
public int bind(PreparedStatement ps) throws SQLException {
if (ps == null) {
return 0;
}
int i = 1;
for (Iterator<GenericColumn> it = ids.iterator(); it.hasNext();) {
GenericColumn column = it.next();
switch (column.getType()) {
case Int:
ps.setInt(i, column.getIntValue());
break;
case Long:
ps.setLong(i, column.getLongValue());
break;
case Double:
ps.setDouble(i, column.getDoubleValue());
break;
case Boolean:
ps.setBoolean(i, column.getBooleanValue());
break;
case Timestamp:
ps.setTimestamp(i, column.getTimestampValue());
break;
case String:
ps.setString(i, column.getStrValue());
break;
}
i++;
}
return i;
}
}
最終的なDAO実装:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.kamike.db;
import com.kamike.db.generic.GenericDelete;
import com.kamike.db.generic.GenericInsert;
import com.kamike.db.generic.GenericUpdate;
import com.kamike.kami.MySQLBucketWriter;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class GenericWriter<T> {
//Protected
protected String tableName;
protected Transaction ts;
protected GenericWriter(Transaction ts, String tableName) {
this.tableName = tableName;
this.ts= ts;
}
public boolean add(T t) {
if (ts == null) {
return false;
}
// String uuid= UUID.randomUUID().toString();
GenericInsert<T> insert = new GenericInsert<>(t);
int success = 0;
PreparedStatement ps = null;
try {
ps = ts.preparedStatement(insert.sql());
insert.bind(ps);
success = ps.executeUpdate();
} catch (Exception e) {
ts.rollback();
System.out.println(this.getClass().getName() + e.toString());
return false;
} finally {
try {
if (ps != null) {
ps.close();
ps = null;
}
} catch (SQLException ex) {
Logger.getLogger(MySQLBucketWriter.class.getName()).log(Level.SEVERE, null, ex);
}
}
return true;
}
public boolean delete(T t) {
if (ts == null) {
return false;
}
// String uuid= UUID.randomUUID().toString();
GenericDelete<T> delete = new GenericDelete<>(t);
int success = 0;
PreparedStatement ps = null;
try {
ps = ts.preparedStatement(delete.sql());
delete.bind(ps);
success = ps.executeUpdate();
} catch (Exception e) {
ts.rollback();
System.out.println(this.getClass().getName() + e.toString());
return false;
} finally {
try {
if (ps != null) {
ps.close();
ps = null;
}
} catch (SQLException ex) {
Logger.getLogger(MySQLBucketWriter.class.getName()).log(Level.SEVERE, null, ex);
}
}
return true;
}
public boolean edit(T t) {
if (ts == null) {
return false;
}
// String uuid= UUID.randomUUID().toString();
GenericUpdate<T> update = new GenericUpdate<>(t);
int success = 0;
PreparedStatement ps = null;
try {
ps = ts.preparedStatement(update.sql());
update.bind(ps);
success = ps.executeUpdate();
} catch (Exception e) {
ts.rollback();
System.out.println(this.getClass().getName() + e.toString());
return false;
} finally {
try {
if (ps != null) {
ps.close();
ps = null;
}
} catch (SQLException ex) {
Logger.getLogger(MySQLBucketWriter.class.getName()).log(Level.SEVERE, null, ex);
}
}
return true;
}
}
最後にTransactionの実装を補足します.ここでは実装方法がたくさんあります.ここで与えられたTransactionはその1つにすぎません.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.kamike.db;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author THiNk
*/
public class Transaction {
protected Connection con;
protected String dbName;
protected boolean rollback;
protected int originalTransactionIsolationLevel;
public Transaction(String dbName) {
this.dbName = dbName;
}
protected void init() {
this.rollback = false;
try {
con = MultiDbInst.getInstance().getDatabase(dbName).getSingleConnection();
con.setAutoCommit(false);
} catch (SQLException ex) {
Logger.getLogger(MySQLTransaction.class.getName()).log(Level.SEVERE, null, ex);
}
}
protected void setTransactionIsolationLevel(int transactionIsolationLevel) {
try {
if (con != null) {
DatabaseMetaData dbmt = con.getMetaData();
if (dbmt.supportsTransactions()) {
if (dbmt.supportsTransactionIsolationLevel(transactionIsolationLevel)) {
originalTransactionIsolationLevel = con.getTransactionIsolation();
con.setTransactionIsolation(transactionIsolationLevel);
}
}
}
} catch (SQLException ex) {
Logger.getLogger(MySQLTransaction.class.getName()).log(Level.SEVERE, null, ex);
}
}
protected void resetTransactionIsolationLevel() {
try {
if (con != null) {
DatabaseMetaData dbmt = con.getMetaData();
if (dbmt.supportsTransactions()) {
if (dbmt.supportsTransactionIsolationLevel(originalTransactionIsolationLevel)) {
con.setTransactionIsolation(originalTransactionIsolationLevel);
}
}
}
} catch (SQLException ex) {
Logger.getLogger(MySQLTransaction.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void save() {
try {
if (this.rollback) {
con.rollback();
} else {
con.commit();
}
} catch (SQLException ex) {
Logger.getLogger(MySQLTransaction.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (con != null) {
con.setAutoCommit(true);
con.close();
con = null;
}
} catch (SQLException ex) {
Logger.getLogger(MySQLTransaction.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/**
* , ,
*/
public void finalize() {
try {
if (con != null) {
con.close();
con = null;
}
} catch (SQLException ex) {
Logger.getLogger(MySQLTransaction.class.getName()).log(Level.SEVERE, null, ex);
}
try {
super.finalize();
} catch (Throwable ex) {
Logger.getLogger(MySQLTransaction.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* @return the ps
*/
public PreparedStatement preparedStatement(String sql) throws SQLException {
return con.prepareStatement(sql, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
}
/**
* @param rollback the rollback to set
*/
public void rollback() {
this.rollback = true;
}
}
最後に、改めて@1兄さんに感謝