总结一下关于JPA的主键生成策略,JPA是用@GeneratedValue标记来注释的。一般的我把主键生成分成两大类。第一个就是简单的单字段主键类型,一个就是复杂的复合主键类型。我们分2种情况分别讨论。
第一种单字段主键类型,看上去简单,无非就是一个id字段呗,实际上这个主键字段在JPA,还有任何的ORM框架中都是有很多种生成策略的。
一般是如下4种:
1. AUTO:自动自增生成
2. TABLE:自定义表生成器
3. Identity:像MS SQL支持Identity字段的生成主键策略
4. Sequence:像Oracle支持Sequence的生成主键策略
1:自动生成主键AUTO
AUTO是默认的主键生成策略,使用了AUTO策略,JPA会根据不同的数据库类型来实现自增策略。比如MySql的表主键是自增1的,那么此策略就会按照数据库的自增1策略,每次插入数据库记录的时候都会自增1。Java代码片段如下:
@Id @GeneratedValue(strategy=GenerationType.AUTO) private Integer id; |
2:自定义表生成器TABLE
自定义表生成器是在数据库中再建立一张新的表,这张表不是业务表,而是一张特殊表,这张表是专门用来管理整个数据库的主键的具体值的。在数据库中建立一张表如下图所示:
那么相应的Java片段如下所示:
@Id @GeneratedValue(strategy = GenerationType.TABLE, generator = "myTablePK") @TableGenerator( name = "myTablePK", table = "tb_pk", pkColumnName = "table_PK_name", pkColumnValue = "tb_contact_pk", valueColumnName = "table_PK_value", allocationSize = 1) private Integer id; |
下面对@TableGenerator标记的属性说明一下:
Name:引用@GeneratedValue里面的generator的值
Table:数据库中专门用于生成主键的特殊表的表名
pkColumnName:tb_pk表中哪个字段代表了被服务(需要生成主键表)的表名
valueColumnName:指定此辅助表的哪个字段存储了主键的具体值
pkColumnValue:指明一个主键名称,依靠这个名称可以在这张特殊表中找到唯一的table_PK_value的值,而这个值就是具体的主键值。换句话说,数据库有几个业务表,这张表就应该有几条记录才对(除去复合主键的情况)
allocationSize:代表自增数
下面自己再写一个测试方法,这次注释掉主键set那一句,代码如下:
/** * 保存ContactEO实体单元测试 * * @throws NamingException */ public void test03() throws NamingException {
// 建立实体 ContactEO contactEO = new ContactEO();
//注释掉主键这句话 //contactEO.setId(2);
contactEO.setName("测试主键table策略");
contactEO.setMessage("表策略");
contactEO.setEmail("[email protected]");
contactEO.setPrice(9999999911.12);
// 对byte属性的赋值 try {
// 读取本机一个文件 File file = new File("c://22.jpg"); if (file != null) { FileInputStream fis = new FileInputStream(file); if (fis != null) { int len = fis.available(); byte[] xml = new byte[len]; fis.read(xml);
// 赋值 contactEO.setPicture(xml); } }
} catch (Exception e) { e.printStackTrace(); }
// 获得应用服务上下文 Context ctx = getInitialContext();
Object object = ctx.lookup("ContactServiceImpl/remote");
// 接口 IContactService contactService = (IContactService) PortableRemoteObject .narrow(object, IContactService.class);
// 调用接口保存方法 contactService.saveContact(contactEO);
} |
执行后,数据库记录如下:
tb_contact记录
可以看到id=4的是tb_pk表辅助生成的值。
tb_pk表记录如下
可以看到,tb_pk这张表的table_PK_value的值改变了。