2011-11-17 30 views
1

我正在开发基于Web的应用程序来替换基于桌面的应用程序。我需要让他们都在同一个数据库上工作。对于基于Web的应用程序,我使用GWT和Hiberate(与Gilead),运行在Tomcat 7.0上。 SQL服务器是MSSQL 2000设置休眠以通过查看数据库来获取下一个密钥

我得到异常:

com.microsoft.sqlserver.jdbc.SQLServerException:PRIMARY KEY约束 'PK_CallLog' 的相关规定。不能在对象'CallLog'中插入重复键。

为了让我做以下步骤除外:

  1. 添加通话记录与旧的应用程序
  2. 添加呼叫纪录(使用Hibernate)的新的应用程序。

看来,hibernate使用自己的缓存,而不是看着数据库来找出下一个主键应该是什么。
有没有办法通过查看数据库强制hibernate获取下一个密钥?

这是呼叫记录的映射:

<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hib.....dtd"> 

<hibernate-mapping> 
    <class name="com.asi.shared.Call" table="CallLog"> 
     <id name="id" column="callid"> 
      <generator class="increment"/> 
     </id>   
     <property name="caller"/> 
     <property name="callDate" column="calldate"/> 
     .... other props .... 
     <property name="checkOut" column="checkout"/> 
     <many-to-one name="customer" class="com.asi.shared.Customer" 
        column="customerid" not-found="ignore"/> 
    </class> 
</hibernate-mapping> 

这是我使用添加一个新的调用方法:

public Integer saveCall(Call call){ 
    DebugLog.print("HelpDeskServiceImpl.saveCall(call)"); 
    Session session = gileadHibernateUtil.getSessionFactory().getCurrentSession(); 
    session.beginTransaction(); 
    check(session); 
    session.saveOrUpdate(call); 
    session.getTransaction().commit(); 
    return call.getId(); 
} 

架构的通话记录:

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[CallLog]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) 
drop table [dbo].[CallLog] 
GO 

CREATE TABLE [dbo].[CallLog] (
    [callid] [int] NOT NULL , 
    [caller] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL , 
    [calldate] [datetime] NULL , 
    .... other columns .... 
    [checkout] [varchar] (5) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 
GO 

我想尽量避免更改数据库,我不想打破旧的应用程序。

回答

0

是,increment发生器使用内部缓存中,当多个进程可以同时访问数据库时,不打算使用它。

假设您不能更改数据库和传统应用程序,并且传统应用程序也使用类似于ID生成策略,唯一可能的解决方案是使用改进的类似于战略的类似increment的策略。

有两个可能的选择:

  • 发出一个查询,以节省每Call之前手动确定值最大的ID,并指定标识手动

  • 看看的IncrementGenerator并实施类似的一个没有缓存值

请注意,这些策略仍然容易受到如果多个交易在同一时刻保存Call,则可能的ID冲突。

如果您可以更改数据库和遗留应用程序,请查看dlamblin的建议。

+0

我采用了第一种策略。只有大约20人会使用它,所以我不认为它会是一个问题,最终遗留的应用程序将被淘汰,所以我会把它切换回来。谢谢您的帮助! – Angel

0

您需要将数据库的定义更改为自动递增该id,然后让hibernate不分配id本身并将其保留到数据库。

[callid] [int] NOT NULL IDENTITY(1, 1), % or (10000, 1) or use the highest id. 

休眠类:

@Id 
@GeneratedValue(strategy=GenerationType.AUTO) 
private int callid; 

或者喜欢的东西什么的记录here把发生器看看数据库去:

<id name="id" column="callid"> 
     <generator class="hilo"> 
      <param name="table">CallLog</param> 
      <param name="column">callid</param> 
     </generator> 
    </id>   
+0

我尝试使用“hilo”,但它生成一个11位数的负数,它不只是采取下一个最高的ID。无论如何,感谢您的帮助。 – Angel

+0

@Angel那么'sequence'或'native'可能就是你要找的东西。它确实选择了遗留应用程序不会选择的唯一ID。身份证号码的价值重要吗?你希望能够通过ID订购电话吗? – dlamblin