hibernate自定义主键生成策略

时间:2021-03-19 13:40:03

package cn.silvernet.util;

import java.io.Serializable;
import java.util.UUID;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IdentifierGenerator;


public class KeyUtils implements IdentifierGenerator {

	@Override
	public Serializable generate(SessionImplementor arg0, Object arg1)
			throws HibernateException {
		// TODO Auto-generated method stub
		return "--"+UUID.randomUUID();//返回自定义生成的主键
	}


}


测试:

public class AddTest {
	
	@Test
	public void addTest() {
		Info info=new Info();
		info.setTitle("新");
		DbCommon.save(info);
	}
}

配置:

<class name="Info" table="t_info">
		<id name="id" column="id">
			<generator class="cn.silvernet.util.KeyUtils"/>
		</id>
		<property name="date" ></property>
		<property name="type" ></property>
		<property name="title" ></property>
		<property name="content" length="20000" ></property>
	</class>

来一个更为直接的例子:

职员的id变为公司id+两位自增id:

package cn.silvernet.util;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.Configurable;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.type.Type;

import cn.silvernet.model.Trader;

@SuppressWarnings({ "unused", "unchecked" })
public class KeyUtilsTrader implements IdentifierGenerator, Configurable {
	private static final int Digit = 2;// 主键位数

	private String className;// 类名
	private String tableName;// 表名
	private String PK;// 主键名
	private long minKey = 1;// 可用的最小主键

	@Override
	public Serializable generate(SessionImplementor arg0, Object arg1)
			throws HibernateException {
		Trader trader = (Trader) arg1;
		// 组织HQL语句查询所有本公司的交易员主键
		String hql = "select o." + this.PK + " from " + this.className
				+ " o where o.company  ='" + trader.getCompany().getId() + "'";
		QueryParameters parameters = new QueryParameters();
		List<String> list = arg0.list(hql, parameters);// 执行hql语句

		List<Long> listLong = new ArrayList<Long>();
		for (String s : list) {
			listLong.add(Long.valueOf(s.substring(trader.getCompany().getId()
					.length(), s.length())));// 除去公司id放入long数组
		}
		// 对交易员表中的id进行排序
		listLong.sort(new Comparator<Long>() {

			@Override
			public int compare(Long o1, Long o2) {
				// TODO Auto-generated method stub
				return (int) (o1 - o2);// 升序
			}
		});
		// 寻找可用的最小主键
		for (int i = 1; i < (int) Math.pow(10, KeyUtilsTrader.Digit); i++) {
			if (i > listLong.size() || listLong.get(i - 1) != i) {
				this.minKey = i;
				break;
			}
		}

		return String.format("%s%0" + KeyUtilsTrader.Digit + "d", trader
				.getCompany().getId(), this.minKey);// 返回自定义生成的主键(公司id+交易员id)
	}

	@Override
	public void configure(Type arg0, Properties arg1, Dialect arg2)
			throws MappingException {

		this.className = arg1
				.getProperty(PersistentIdentifierGenerator.JPA_ENTITY_NAME);
		this.tableName = arg1.getProperty(PersistentIdentifierGenerator.TABLE);
		this.PK = arg1.getProperty(PersistentIdentifierGenerator.PK);

	}

}