JPA学习笔记-EJB-03JPA主键生成策略总结--1
总结一下关于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("suhuanzheng77848@163.com");
?
?????? 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的值改变了。
?
?