1

デスクトップベースのアプリケーションを置き換える Web ベースのアプリケーションを開発しています。両方を同じデータベースで動作させる必要があります。Web ベースのアプリケーションでは、GWT と Hiberate (Gilead を使用) を使用し、Tomcat 7.0 で実行しています。SQL サーバーは MSSQL 2000 です。

私は例外を取得しています:

com.microsoft.sqlserver.jdbc.SQLServerException: PRIMARY KEY 制約 'PK_CallLog' の違反。オブジェクト 'CallLog' に重複するキーを挿入できません。

例外を取得するには、次の手順を実行します。

  1. 旧アプリで通話記録を追加する
  2. 新しいアプリケーションで通話記録を追加します (休止状態を使用)。

休止状態は独自のキャッシュを使用しており、次の主キーがどうあるべきかを把握するためにデータベースを調べていないようです。
データベースを見て、休止状態に強制的に次のキーを取得させる方法はありますか?

これは、通話記録のマッピングです。

<?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

データベースの変更はできるだけ避けたい、古いアプリケーションを壊したくない。

4

2 に答える 2

0

はい、incrementジェネレーターは内部キャッシュを使用し、複数のプロセスが同時にデータベースにアクセスできる場合に使用することを意図していません。

データベースとレガシー アプリケーションを変更することはできず、そのレガシー アプリケーションincrementも -like id 生成戦略を使用すると仮定すると、唯一可能な解決策は、改善されたincrement-like 戦略を使用することです。

次の 2 つのオプションがあります。

  • それぞれを保存する前に手動で最大 ID 値を決定するクエリを発行し、手動Callで識別子を割り当てます

  • を見てIncrementGenerator、値をキャッシュせずに同様のものを実装します

これらの戦略は、複数のトランザクションCallがまったく同時に保存された場合、ID の衝突に対して依然として脆弱であることに注意してください。

データベースとレガシー アプリケーションを変更できる場合は、dlamblin の提案を参照してください。

于 2011-11-17T17:42:52.807 に答える
0

データベースの定義を変更してそのIDを自動インクリメントする必要があります。次に、ID自体を割り当てずにデータベースに任せるようにhibernateに指示します。

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

休止状態のクラス:

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

または、ジェネレーターがデータベースを確認するために、ここに記載されているようなものを使用します。

    <id name="id" column="callid">
        <generator class="hilo">
          <param name="table">CallLog</param>
          <param name="column">callid</param>
        </generator>
    </id>        
于 2011-11-17T17:34:04.117 に答える