今天在将监控管理工程底层的持久化实现从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)
@javax.persistence.GeneratedValue(generator="project-assigned")
@org.hibernate.annotations.GenericGenerator(name="project-assigned",strategy="assigned")
public Long getTargetConfigId() {
return this.targetConfigId;
}
这样加的注解,在直接用hibernate的session进行操作时,是不会有问题的,但是用JPA的EntityManager接口进行操作时,就报了上面的错误。
在JPA中,可以为entity bean手工生成主键,也可以让persistence provider为你代劳。当你想让persistence provider生成主键时,就必须使用注解@javax.persistence.GeneratedValue。
@javax.persistence.GeneratedValue的定义如下
package javax.persistence;
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface GeneratedValue{
GenerationType strategy() default AUTO;
String generator() default "";
}
public enum GenerationType{
TABLE, SEQUENCE, IDENTITY, AUTO
}
在监控管理工程中,所有的主键的生成都是手工为entity bean生成主键,再通过主键属性的set方法设置进entity bean里的,所以在使用JPA方式操作时,本来就不应该使用GeneratedValue这个注解。
在如上面忘记修改注解的情况下,JPA认定我的主键需要persistence provider来生成,而且生成策略使用默认即GenetionType.AUTO。所以在我已经手工为entity bean设置了主键属性的值,再通过EntityManager接口的persist方法进行游离对象的持久化时,就报出了开头的那个错误。
修改后的注解如下
@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来设置使用表生成器进行主键生成。
分享到:
相关推荐
ORMCodeGenerator2.1中文版Nhibernate代码生成器 此版本吸取前几个版中的优点,增加了更多功能.修改了以前的一些BUG 特点: 1.... 2.数据支持Access2000/2003 MSSQL...2.表出现联合主键时生成错误.(映射文件中主键生成错误
如何使用Myeclipse生成映射文件和实体类? 映射文件和实体类《=========》DB 1)如何根据DB生成实体类和映射文件 =========利用Myeclipse追加Hibernate框架======== a.先在DB Browser窗口建立一个与数据库的连接 ...
动软.Net代码生成器 是一款为C#数据库程序员...5. 页面代码生成包含主键的问题。 6. 增加了Access数据库字段类型映射机制。 7. 增加了查看Oracle的存储过程。 问题解决: 解决,本机没有安装Office2007而导致的错误
5. 页面代码生成包含主键的问题。 6. 增加了Access数据库字段类型映射机制。 7. 增加了查看Oracle的存储过程。 问题解决: 解决,本机没有安装Office2007而导致的错误。 作者:李天平 源码下载及讨论地址:...
一直以来根据数据库表结构自动生成项目框架代码都是一件让人很头痛的事情,如果能自动生成框架的... 5、Entity主键生成策略新增identity和sequence。 6、开放自定义作者的配置。 7、修复一些Bug并进行了一些优化。
系统实现了比较完整的O-R映射,数据库中的所有逻辑对象表,列,字段,主键,外键,Null,Default,唯一索引都在类里得到了体现,同时还支持代码表,代码列,自增长机制 系统支持完整的数据操作功能,支持带事务功能...
从数据库中提取表对应的C#实体代码,目前支持Oracle、SqlServer数据库,并可从对应类型的数据库中提取表及字段的注释,并可对生成的实体数据类型等进行各种自定义的设置等。如数据库列和C#代码类型的映射、实体命名...
包括:结构迁移:支持字段类型、主键信息、建表语句等的转换,并生成建表SQL语句。支持基于正则表达式转换的表名与字段名映射转换。数据同步:基于JDBC的分批次读取源端数据库数据,并基于insert/copy方式将数据分...
生成Mapper映射文件(dao层接口SQL语句,支持生成3表关联(比如:A表关联B表,B表关联C表,一次便可获得3张表的数据),支持主键策略;<如果选择创建Assist支持分页,去重,排序,无注入动态查询等>); 生成service层接口(与dao...
支持字段类型、主键信息、建表语句等的转换,并生成建表SQL语句。支持基于正则表达式转换的表名与字段名映射转换。基于JDBC的分批次读取源端数据库数据,并基于insert/copy方式将数据分批次写入目的数据库。支持有...
从数据库中生成表对应的VB/C#实体代码,并提取表及字段的注释等信息,亦可对生成的实体数据类型进行各种自定义的设置和方便的数据库操作等。如数据库列和VB/C#代码类型的映射、实体命名空间、代码个性化注释、是否...
包括:结构迁移:支持字段类型、主键信息、建表语句等的转换,并生成建表SQL语句。支持基于正则表达式转换的表名与字段名映射转换。数据同步:基于JDBC的分批次读取源端数据库数据,并基于insert/copy方式将数据分...
UI界面应用MVC模式,将这个UI界面代码部分分为三部分:视图部分,模型部分和控制,自动生成Data Source属性来完成view和Model的相互映射;并且能按照功能组生成菜单, 同时系统能自动完成null, PK ,UK等基本的数据检验和...
从数据库中生成表对应的VB/C#实体代码,并提取表及字段的注释等信息,亦可对生成的实体数据类型进行各种自定义的设置和方便的数据库操作等。如数据库列和VB/C#代码类型的映射、实体命名空间、代码个性化注释、是否...
从数据库中提取表对应的C#实体代码,目前支持Oracle、SqlServer数据库,并可从对应类型的数据库中提取表及字段的注释,并可对生成的实体数据类型等进行各种自定义的设置,如数据库列和C#代码类型的映射、实体命名...
从数据库中生成表对应的VB/C#实体代码,并提取表及字段的注释等信息,亦可对生成的实体数据类型进行各种自定义的设置和方便的数据库操作等。如数据库列和VB/C#代码类型的映射、实体命名空间、代码个性化注释、是否...
从数据库中生成表对应的VB/C#实体代码,并提取表及字段的注释等信息,亦可对生成的实体数据类型进行各种自定义的设置和方便的数据库操作等。如数据库列和VB/C#代码类型的映射、实体命名空间、代码个性化注释、是否...
从数据库中提取表对应的C#实体代码,目前支持Oracle、SqlServer、Access数据库,可直接从对应类型的数据库中提取表及字段的注释,并可对生成的实体数据类型等进行各种自定义的设置等。如数据库列和C#代码类型的映射...
从数据库中生成表对应的VB/C#实体代码,并提取表及字段的注释等信息,亦可对生成的实体数据类型进行各种自定义的设置和方便的数据库操作等。如数据库列和VB/C#代码类型的映射、实体命名空间、代码个性化注释、是否...
从数据库中生成表对应的VB/C#实体代码,并提取表及字段的注释等信息,亦可对生成的实体数据类型进行各种自定义的设置和方便的数据库操作等。如数据库列和VB/C#代码类型的映射、实体命名空间、代码个性化注释、是否...