读书人

数据主键生成映射有关问题

发布时间: 2012-10-29 10:03:53 作者: rapoo

数据主键生成映射问题

今天在将监控管理工程底层的持久化实现从hibernate换成JPA时还是遇到问题了,EntityManager在调用persist时报出了

feng-15:37:15,620 ERROR [STDERR] javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: ejbModule.domain.targetconfig.TTargetConfig

feng-15:37:15,620 ERROR [STDERR] at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:629)

feng-15:37:15,620 ERROR [STDERR] at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:218)

feng-15:37:15,620 ERROR [STDERR] at org.jboss.ejb3.entity.TransactionScopedEntityManager.persist(TransactionScopedEntityManager.java:182)

feng-15:37:15,620 ERROR [STDERR] at ejbModule.persistence.common.AbstractDaoImpl.save(AbstractDaoImpl.java:348)

feng-15:37:15,620 ERROR [STDERR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

...

feng-15:37:15,625 ERROR [STDERR] Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: ejbModule.domain.targetconfig.TTargetConfig

feng-15:37:15,625 ERROR [STDERR] at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:79)

feng-15:37:15,625 ERROR [STDERR] at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38)

feng-15:37:15,625 ERROR [STDERR] at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:618)

feng-15:37:15,625 ERROR [STDERR] at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:592)

feng-15:37:15,625 ERROR [STDERR] at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:596)

feng-15:37:15,625 ERROR [STDERR] at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:212)

feng-15:37:15,627 ERROR [STDERR] ... 66 more

?

后来才发现了是由于实体的主键属性上加了注解如下:

?

@javax.persistence.Id@javax.persistence.Column(name="TARGET_CONFIG_ID",scale=0)public Long getTargetConfigId() {return this.targetConfigId;}
?

----------------------------------------------大家一起来分隔---------------------

关于主键生成,现在工程里都是通过用一张数据库表:SEQ表,来进行主键的生成。

每次需要往数据库里插入新数据时,都需要从这张SEQ表里查找出当前已使用主键的数值,再对这个当前数值进行操作,得到一个不同于当前已经使用的主键数值(现在使用的方法是进行加1累加),最后再更新这张SEQ表的当前已使用主键值。这样就得到了一个还没进行使用的主键数值。

  可是这样的问题是每次插入数据时,都得跟数据库进行生成主键的操作往返,无疑增加了数据库的负担,在大量并发地插入数据时,这样的问题更为明显。

  后来这张SEQ表由于并发访问大经常被锁定了,导致程序无法对其进行操作。在进行了使用BEAN管理事务的方法对生成主键的代码进行事务管理,还在stateless bean里加synchronized进行并发控制...都不起作用的情况下,最后对SEQ表进行了分表,一张SEQ表分成了A_SEQ,B_SEQ,C_SEQ表等等,各个模块对生成主键并发访问量大的另外访问这些分出来的SEQ表,减少对同一张SEQ表访问量。这样下来才基本解决了锁表问题,可是以后会不会再出现,我也不知道了......

就这个问题,后来我有考虑过使用数据库的触发器来自动生成主键值,可是被P总否定了,理由是数据量太大时,使用触发器会使数据库的操作变慢...我没经历过这么大量数据的测试,也不知道是不是会这样,反正否决不了他做的决定...

?

所以现在数据主键的生成还是通过程序查表来进行操作,下一步我想考虑通过使用@GeneratedValue来设置使用表生成器进行主键生成。

?

读书人网 >软件架构设计

热点推荐