分表

        刚完成的项目需求:一个全省范围内的项目,所有市访问同一个网站,所有市对自身的数据有管理权限;在这些数据中,一公告这么一个实体,所有管理员均可向这张表中写入数据,每个月的数据都会超过万条。为避免公告表变成巨无霸,现将公告表按区域、公告类型分表。

        主要代码就一个类:

/**
 * 
 */
package com.hbcgs.notice.interceptor;

import org.hibernate.EmptyInterceptor;

/**
 * @author Geloin
 * 
 */
@SuppressWarnings("serial")
public class NoticeInfoInterceptor extends EmptyInterceptor {

	private String targetTableName;// 目标母表名
	private String tempTableName;// 操作子表名

	public NoticeInfoInterceptor() {
	}// 为其在spring好好利用 我们生成公用无参构造方法

	@Override
	public java.lang.String onPrepareStatement(java.lang.String sql) {
		sql = sql.replaceAll(targetTableName, tempTableName);
		return sql;

	}

	public String getTargetTableName() {
		return targetTableName;
	}

	public void setTargetTableName(String targetTableName) {
		this.targetTableName = targetTableName;
	}

	public String getTempTableName() {
		return tempTableName;
	}

	public void setTempTableName(String tempTableName) {
		this.tempTableName = tempTableName;
	}

}

        在控制分表时,在管理数据层,假设是Dao层,进行以下处理:

	/**
	 * 保存公告信息,分表保存
	 * 
	 * @param info
	 */
	public void save(NoticeInfo info) {

		SessionFactory sf = super.getHibernateTemplate().getSessionFactory();

		NoticeInfoInterceptor interceptor = new NoticeInfoInterceptor();

		// 要拦截的目标表名
		interceptor.setTargetTableName("noticeinfo");

		String realTableName = "NOTICEINFO_" + info.getArea().getAreaId() + "_"
				+ info.getType();

		// 要替换的子表名
		interceptor.setTempTableName(realTableName);

		try {
			if (!existsTableNames.contains(realTableName)) {
				checkTable(sf.openSession(), realTableName);
				existsTableNames.add(realTableName);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		Session session = sf.openSession(interceptor);

		try {
			// 获取事务
			Transaction tx = session.beginTransaction();
			// 开启事务
			tx.begin();
			// 保存和更新
			session.saveOrUpdate(info);
			// 提交
			tx.commit();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			session.close();
		}

	}

        Dao层继承了org.springframework.orm.hibernate3.support.HibernateDaoSupport类,checkTable方法主要是为了检查表是否存在,不存在时需要建表:

	/**
	 * 检查表是否存在,不存在时创建
	 * 
	 * @param session
	 * @param tableName
	 * @throws Exception
	 */
	private void checkTable(Session session, String tableName) throws Exception {

		try {
			// 测试查询
			String testSql = "select * from " + tableName;
			Query query = session.createSQLQuery(testSql);
			query.setFirstResult(0);
			query.setMaxResults(1);
			query.uniqueResult();
		} catch (HibernateException e) {
			// Connection conn = session.connection();
			// Statement stmt = conn.createStatement();
			StringBuilder builder = new StringBuilder();
			builder.append("create table ");
			builder.append(tableName);
			builder.append("(");
			builder.append("ID      NUMBER(10) not null,");
			builder.append("STR1    VARCHAR2(255),");
			builder.append("STR2    VARCHAR2(255),");
			builder.append("STR3    VARCHAR2(255),");
			builder.append("STR4    VARCHAR2(255),");
			builder.append("STR5    VARCHAR2(255),");
			builder.append("STR6    VARCHAR2(255),");
			builder.append("STR7    VARCHAR2(255),");
			builder.append("STR8    VARCHAR2(255),");
			builder.append("STR9    VARCHAR2(255),");
			builder.append("STR10   VARCHAR2(255),");
			builder.append("PYEAR   NUMBER(10),");
			builder.append("PMONTH  NUMBER(10),");
			builder.append("TYPE    NUMBER(10),");
			builder.append("AREA_ID NUMBER(10)");
			builder.append(")");

			Query query = session.createSQLQuery(builder.toString());
			query.executeUpdate();

		} finally {
			session.flush();
			session.close();
		}
	}

        实现方法显然比较粗糙,不过暂时够解决问题,Mark一下。

 


你可能感兴趣的:(spring,Hibernate,分表)