アーカイブ水平表
11289 ワード
ここでのアーカイブ水平分割テーブルは、1枚のテーブル内のデータが一定時間または一定のステータスビット変化を経た後、このデータをテーブルから消去してパフォーマンスを向上させ、消去したデータをアーカイブテーブルに格納する必要があることを意味します.この記事では、アーカイブ・テーブルのデータを読み取り、アーカイブ・テーブルのデータを元のテーブルに再移動できるようにコードを変更する方法について説明します.
コードはjava、hibernate、mysqlを例に挙げます.
まずタイマを作成し,タイミングよくデータをアーカイブテーブルにアーカイブし,SysAccountアカウントテーブルをSysAccountArテーブルにアーカイブする例を示す.SysAccountテーブルのプライマリ・キーは自己増加し、SysAccountArテーブルのプライマリ・キーは自己増加を設定せず、プライマリ・テーブルからアーカイブされたデータのプライマリ・キーを使用します.
その後、できるだけ少ない変更コードが採用され、ここではhibernateのentity-name機能が採用されている.すなわち、hbmのみがエンティティクラスを作成する必要はない.xml,得られた単一エンティティデータはMap形式,keyはクラスの属性,valueは値である.
SysAccount.hbm.xmlの内容は以下の通りです.
SysAccountAr.hbm.xmlの内容は以下の通りです.
違いは、アーカイブ・テーブルのidを自己増加ではなく指定に設定する必要があることです.
entity-nameの値はhql文のテーブル名なので、パッケージ名を付けなくても簡潔です
entity-nameで検索したのはMapなので、Mapとエンティティークラスが互いに変換する方法が必要で、他のサイトで検索することができます.例えば
そしてdao層の操作
以上の機能には、エンティティをアーカイブ・テーブルに保存したり、アーカイブ・テーブルからエンティティを読み出したり、アーカイブ・テーブルのレコードをプライマリ・テーブルに移動したりする機能があります.
その後の拡張には、2次アーカイブ・テーブルの作成、プライマリ・テーブルに依存する他のプライマリ・テーブルのアーカイブ・テーブルの作成などが含まれます.
コードはjava、hibernate、mysqlを例に挙げます.
まずタイマを作成し,タイミングよくデータをアーカイブテーブルにアーカイブし,SysAccountアカウントテーブルをSysAccountArテーブルにアーカイブする例を示す.SysAccountテーブルのプライマリ・キーは自己増加し、SysAccountArテーブルのプライマリ・キーは自己増加を設定せず、プライマリ・テーブルからアーカイブされたデータのプライマリ・キーを使用します.
その後、できるだけ少ない変更コードが採用され、ここではhibernateのentity-name機能が採用されている.すなわち、hbmのみがエンティティクラスを作成する必要はない.xml,得られた単一エンティティデータはMap形式,keyはクラスの属性,valueは値である.
SysAccount.hbm.xmlの内容は以下の通りです.
<hibernate-mapping>
<class name="com.rbac.entity.SysAccount" table="sys_account" catalog="rbac" dynamic-insert="true" dynamic-update="true">
<id name="id" type="java.lang.Long">
<column name="ID" />
<generator class="native" />
</id>
<property name="username" type="java.lang.String">
<column name="USERNAME" length="20" not-null="true">
<comment> </comment>
</column>
</property>
</class>
</hibernate-mapping>
SysAccountAr.hbm.xmlの内容は以下の通りです.
<hibernate-mapping>
<class entity-name="SysAccountAr" table="sys_account_ar" catalog="rbac" dynamic-insert="true" dynamic-update="true">
<id name="id" type="java.lang.Long">
<column name="ID" />
<generator class="assigned" />
</id>
<property name="username" type="java.lang.String">
<column name="USERNAME" length="20" not-null="true">
<comment> </comment>
</column>
</property>
</class>
</hibernate-mapping>
違いは、アーカイブ・テーブルのidを自己増加ではなく指定に設定する必要があることです.
entity-nameの値はhql文のテーブル名なので、パッケージ名を付けなくても簡潔です
entity-nameで検索したのはMapなので、Mapとエンティティークラスが互いに変換する方法が必要で、他のサイトで検索することができます.例えば
package com.rbac.util;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Map;
import org.apache.commons.beanutils.PropertyUtils;
public class MapConvertUtil {
/**
* Map<String,Object> , java
* @param clazz
* @param map Map
* @return
*/
public static Object mapToObject(Class clazz, Map<String,Object> map){
if(map == null){
return null;
}
Field[] fields = clazz.getDeclaredFields();
Field field;
Object o = null;
try {
o = clazz.newInstance();
} catch (InstantiationException e1) {
e1.printStackTrace();
} catch (IllegalAccessException e1) {
e1.printStackTrace();
}
for(int i=0; i<fields.length; i++){
field = fields[i];
String fieldName = field.getName();
// null
if(map.get(fieldName)==null){
continue;
}
//
String stringLetter=fieldName.substring(0, 1).toUpperCase();
// set , setId
String setterName="set"+stringLetter+fieldName.substring(1);
Method setMethod = null;
Class fieldClass = field.getType();
try {
if(isHaveSuchMethod(clazz, setterName)){
if(fieldClass == String.class){
setMethod = clazz.getMethod(setterName, fieldClass);
setMethod.invoke(o, String.valueOf(map.get(fieldName)));
}else if(fieldClass == Integer.class || fieldClass == int.class){
setMethod = clazz.getMethod(setterName, fieldClass);
setMethod.invoke(o, Integer.parseInt(String.valueOf(map.get(fieldName))));
}else if(fieldClass == Boolean.class || fieldClass == boolean.class){
setMethod = clazz.getMethod(setterName, fieldClass);
setMethod.invoke(o, Boolean.getBoolean(String.valueOf(map.get(fieldName))));
}else if(fieldClass == Short.class || fieldClass == short.class){
setMethod = clazz.getMethod(setterName, fieldClass);
setMethod.invoke(o, Short.parseShort(String.valueOf(map.get(fieldName))));
}else if(fieldClass == Long.class || fieldClass == long.class){
setMethod = clazz.getMethod(setterName, fieldClass);
setMethod.invoke(o, Long.parseLong(String.valueOf(map.get(fieldName))));
}else if(fieldClass == Double.class || fieldClass == double.class){
setMethod = clazz.getMethod(setterName, fieldClass);
setMethod.invoke(o, Double.parseDouble(String.valueOf(map.get(fieldName))));
}else if(fieldClass == Float.class || fieldClass == float.class){
setMethod = clazz.getMethod(setterName, fieldClass);
setMethod.invoke(o, Float.parseFloat(String.valueOf(map.get(fieldName))));
}else if(fieldClass == BigInteger.class ){
setMethod = clazz.getMethod(setterName, fieldClass);
setMethod.invoke(o, BigInteger.valueOf(Long.parseLong(String.valueOf(map.get(fieldName)))));
}else if(fieldClass == BigDecimal.class){
setMethod = clazz.getMethod(setterName, fieldClass);
setMethod.invoke(o, BigDecimal.valueOf(Double.parseDouble(String.valueOf(map.get(fieldName)))));
}else if(fieldClass == Date.class){
setMethod = clazz.getMethod(setterName, fieldClass);
if(map.get(fieldName).getClass() == java.sql.Date.class){
setMethod.invoke(o, new Date(((java.sql.Date)map.get(fieldName)).getTime()));
}else if(map.get(fieldName).getClass() == java.sql.Time.class){
setMethod.invoke(o, new Date(((java.sql.Time)map.get(fieldName)).getTime()));
}else if(map.get(fieldName).getClass() == java.sql.Timestamp.class){
setMethod.invoke(o, new Date(((java.sql.Timestamp)map.get(fieldName)).getTime()));
}
}
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return o;
}
/**
*
* @param clazz
* @param methodName
* @return
*/
private static boolean isHaveSuchMethod(Class<?> clazz, String methodName){
Method[] methodArray = clazz.getMethods();
boolean result = false;
if(null != methodArray){
for(int i=0; i<methodArray.length; i++){
if(methodArray[i].getName().equals(methodName)){
result = true;
break;
}
}
}
return result;
}
/**
* Map, java
* @param entity
* @return
*/
public static Map objectToMap(Object entity){
try {
return PropertyUtils.describe(entity);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
}
そしてdao層の操作
package com.rbac.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.Hibernate;
import org.springframework.stereotype.Component;
import com.rbac.common.BaseDaoSupport;
import com.rbac.entity.SysAccount;
import com.rbac.util.MapConvertUtil;
@Component("archiveDao")
public class ArchiveDao extends BaseDaoSupport{
public void saveOrUpdateAccountAr(SysAccount account){
super.getHibernateTemplate().saveOrUpdate("SysAccountAr", account);
}
public void saveOrUpdateAccountAr(Map map){
super.getHibernateTemplate().saveOrUpdate("SysAccountAr", map);
}
public SysAccount getAccountById(Long id){
// HibernateDaoSupport.getSession initialize
// getHibernateTemplate collection is not associated with any session
SysAccount account = (SysAccount)super.getSession().get(SysAccount.class, id);
return account;
}
public Map getAccountArById(Long id){
Map map = (Map)super.getSession().get("SysAccountAr", id);
return map;
}
/**
* , ,
* @param username
* @return HashMap, key SysAccount, key SysAccountAr
*/
public Map<String,SysAccount> loadByNameIncludeAr(String username){
Map<String,SysAccount> tableEntityMap = new HashMap<String,SysAccount>();
List accountList = super.getSession().createQuery("from SysAccount where username=:username").setString("username", username).list();
if(accountList.size()>0){
tableEntityMap.put("SysAccount", (SysAccount)accountList.get(0));
return tableEntityMap;
}
List accountArList = super.getSession().createQuery("from SysAccountAr where username=:username").setString("username", username).list();
if(accountArList.size()>0){
Map accountArMap = (Map)accountArList.get(0);
SysAccount account = (SysAccount)MapConvertUtil.mapToObject(SysAccount.class, accountArMap);
tableEntityMap.put("SysAccountAr", account);
return tableEntityMap;
}
return tableEntityMap;
}
/**
* SysAccount, tabelname , ,
* @param tableName SysAccount, SysAccountAr
* @param account
*/
public void saveOrUpdateAccount(String tableName, SysAccount account) throws Exception{
if("SysAccount".equals(tableName)){
super.getSession().saveOrUpdate(account);
}
else if("SysAccountAr".equals(tableName)){
if(account.getId()==null){
throw new Exception(" id");
}
Map arMap = MapConvertUtil.objectToMap(account);
super.getSession().saveOrUpdate("SysAccountAr", arMap);
}
}
/**
* ,id
* @param username
*/
public void moveAccountFromAr(String username) throws Exception{
Map<String,SysAccount> map = loadByNameIncludeAr(username);
if(map.containsKey("SysAccountAr")){
SysAccount account = map.get("SysAccountAr");
Long arId = account.getId();
// , arId
if(super.getSession().get(SysAccount.class, arId)!=null){
throw new Exception("id "+arId+",username "+username+" ");
}
// id, , , save id
// persist detached entity passed to persist
// save , id , save
// saveOrUpdate , account
super.getSession().save(account);
// arId
super.getSession().createQuery("update SysAccount set id=:arId where id=:id").setLong("arId", arId).setLong("id", account.getId()).executeUpdate();
//
super.getSession().createQuery("delete from SysAccountAr where id=:id").setLong("id", arId).executeUpdate();
}
else{
throw new Exception(" "+username);
}
}
}
以上の機能には、エンティティをアーカイブ・テーブルに保存したり、アーカイブ・テーブルからエンティティを読み出したり、アーカイブ・テーブルのレコードをプライマリ・テーブルに移動したりする機能があります.
その後の拡張には、2次アーカイブ・テーブルの作成、プライマリ・テーブルに依存する他のプライマリ・テーブルのアーカイブ・テーブルの作成などが含まれます.