首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

JPA annotation 学习札记(二)

2012-10-28 
JPA annotation 学习笔记(二)@Id 顾名思义,就不多说了。@GeneratedValue:主键的产生策略,通过strategy属性

JPA annotation 学习笔记(二)
@Id 顾名思义,就不多说了。

@GeneratedValue:主键的产生策略,通过strategy属性指定。
默认情况下,JPA自动选择一个最适合底层数据库的主键生成策略,如SqlServer对应identity,MySql对应auto increment。
在javax.persistence.GenerationType中定义了以下几种可供选择的策略:
1) IDENTITY:表自增键字段,Oracle不支持这种方式;
2) AUTO: JPA自动选择合适的策略,是默认选项;
3) SEQUENCE:通过序列产生主键,通过@SequenceGenerator注解指定序列名,MySql不支持这种方式;
4) TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。

这里我重点来说下GenerationType.TABLE的情况。
把库表的主键auto_increment去掉

CREATE TABLE `t_creditcard` (     `id` int(11) NOT NULL,     `cardName` varchar(20) NOT NULL,     PRIMARY KEY  (`id`)   ) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE `id_gen` (  `gen_name` varchar(80) NOT NULL default '',  `gen_val` int(11) default NULL,  PRIMARY KEY  (`gen_name`)) ENGINE=InnoDB DEFAULT CHARSET=gbk;


@Entity@Table(name="t_creditcard")public class CreditCard{@TableGenerator(name = "CardPkGen",      table = "ID_GEN",      pkColumnName = "GEN_NAME",       pkColumnValue = "Card_Gen",       valueColumnName = "GEN_VAL",       allocationSize = 1)@Id@GeneratedValue(strategy=GenerationType.TABLE,generator="CardPkGen")private Long id;


@GeneratedValue:定义主键生成策略,这里因为使用的是TableGenerator,所以,主键的生成策略为GenerationType.TABLE,生成主键策略的名称则为前面定义的"CardPkGen”。
@TableGenerator各属性含义如下:
name:表示该表主键生成策略的名称,这个名字可以自定义,它被引用在@GeneratedValue中设置的"generator"值中
table:表示表生成策略所持久化的表名,说简单点就是一个管理其它表主键的表,本例中,这个表名为ID_GEN
pkColumnName:表生成器中的列名,用来存放其它表的主键键名,一般来说一个主键键名对应一张其他表要获取主键值对应的key。这个值要与数据库的列对应,比如GEN_NAME对应id_gen中的主键名称
pkColumnValue:该实体所要访问对应主键生成表的主键的key值
valueColumnName:表生成器所要对应pkColumnName主键的下一个值,这个值也要和表生成器中的列名对应
allocationSize:表示每次主键值增加的大小,例如设置成1,则表示每次创建新记录后自动加1,默认为50

按照以上结构,如果我们执行:
CreditCard cc = new CreditCard();cc.setCardName("测试卡");cc = ccDao.persist(cc);

表id_gen内的数据为

GEN_NAME GEN_VALUE
Card_Gen  2

表t_creditcard内的数据为

ID CARDNAME
1   测试卡

再执行一次程序
表id_gen内的数据为

GEN_NAME GEN_VALUE
Card_Gen  3

表t_creditcard内的数据为

ID CARDNAME
1   测试卡
2   测试卡

把实体类的annation改写为:
@Entity@Table(name="t_creditcard")public class CreditCard{@TableGenerator(name = "CardPkGen",      table = "ID_GEN",      pkColumnName = "GEN_NAME",       pkColumnValue = "Card_Gen2",       valueColumnName = "GEN_VAL",       allocationSize = 1)@Id@GeneratedValue(strategy=GenerationType.TABLE,generator="CardPkGen")private Long id;

注意看,pkColumnValue已经被改为Card_Gen2。

执行程序,插入数据失败,抛出t_creditcard表主键重复的异常,因为这次去名为Card_Gen2的这个主键生成器去拿来的id为1,t_creditcard表之前已经插入过一条主键为1的数据了。

表id_gen内的数据为

GEN_NAME GEN_VALUE
Card_Gen  3
Card_Gen2  2

表t_creditcard内的数据还是为

ID CARDNAME
1   测试卡
2   测试卡

结论:在有些应用中,我们可以适用@TableGenerator来统一管理我们数据库中的各个表的主键生成,如果我们的应用中有10个实体需要使用自动生成的主键,只需在每个实体中使用@TableGenerator并给出不同的pkColumnValue值就可以了。

@Id还有一些另类的用法:

1.使用系统毫秒数作为主键
@Idprivate Long id = System.currentTimeMillis();CreditCard cc = new CreditCard();cc.setCardName("测试卡");cc = ccDao.persist(cc);


2.使用UUID作为主键
@Idprivate String id;;CreditCard cc = new CreditCard();cc.setId(UUID.randomUUID().toString());cc.setCardName("测试卡");cc = ccDao.persist(cc);


别忘了修改库表中主键字段的大小和对应的类型. 1 楼 xiaofengtoo 2008-12-06   学习了,@TableGenerator 有必要用吗? 2 楼 kj2ff 2008-12-06   xiaofengtoo 写道
学习了,@TableGenerator 有必要用吗?

我在实际生产项目中没有用过,不过按照它的特性,一些项目中是可以使用,把各表的主键统一管理起来,并且不存在数据库移植到问题。 3 楼 sway 2008-12-09   一直用hibernate的uuid,jpa本身不支持.....

热点排行