0

私はユーザー認証を使用してWebSocketサーバーで作業しています。私は今、このユーザーをリクエストの中に保存する方法を実際には知りません。私のWebSocket接続はおそらく何時間も開いたままになり、1分あたり100リクエストを受信することもあれば、1時間あたり2リクエストを受信することもあります(予測できません)。ユーザーデータは別のアプリケーションによって変更される可能性があります。これは私の質問ではありませんが、関連がある可能性があります。Spring3とHibernate3.6.9を使用しています。

私の質問は、特定のトランザクション管理を使用する必要があり、これらのユーザーデータをどのように管理するかです。

私は2つのユースケースをテストしました:

1.ログイン時にユーザーエンティティをロードし、各リクエストでそれをmerge()します。リクエストごとにトランザクションが閉じられるため、マージする必要があります。マージはデータベースエンティティをロードせず、マージされたエンティティを保持するため、適切なソリューションではありません。したがって、データがどこか別の場所で更新された場合、データは元に戻され、更新されたデータは読み込まれません。

2.ログイン時に、ユーザーIDのみを保存し、リクエストごとにユーザーをfind()します。データベースリクエストのフラッドを回避するために、第2レベルのキャッシュを設定しましたが、SQLサーバーのログによると、hibernateはfind()ごとにリクエストを実行します。

ここにいくつかの具体的なコードと構成があります:

persistence.xml

<persistence-unit name="greenpacs">
<provider>org.hibernate.ejb.HibernatePersistence</provider>

<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
    <property name="hibernate.archive.autodetection" value="class"/>
    <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
    <property name="hibernate.hbm2ddl.auto" value="update"/>
    <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/>

    <property name="hibernate.show_sql" value="true"/>
    <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/db"/>
    <property name="hibernate.connection.user" value="root"/>
    <property name="hibernate.connection.password" value="password"/>
    <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
</properties>
</persistence-unit>

applicationContext.xml

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="greenpacs" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

ユーザーエンティティ

@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class User {
@Id
@Column(name = "userId", unique = true, nullable = false)
private Integer id;

private String pwd;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "User_Role", joinColumns = { @JoinColumn(name = "user_id", referencedColumnName = "userId") }, inverseJoinColumns = { @JoinColumn(name = "role_id", referencedColumnName = "id") })
private List<Role> roles;

@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name="id")
private Person person;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user", cascade = CascadeType.ALL)
private List<Pacs> pacs;

// getter&setter

WebSocketリスナー

@Component
public class UserManager implements WampMessageHandler {

UserService userService;
//Autowired setter

    User user;

@Override
public void onConnected(WampConnection connection) {
       //loginmethod return userId
       user = userService.find(userId);
    }

@Transactional
@Override
public boolean onMessage(String sessionId, int messageType, Object[] msg)
        throws BadMessageFormException {
    user = userService.merge(user);  
            //or  
            user = userService.find(user.getId());  
            ...
}

私のUserServiceは、EntityManagerのメソッドにリダイレクトするだけです。

4

1 に答える 1

1

2番目の解決策は明らかなもののように見えます。hibernate.cache.use_second_level_cacheプロパティをに設定しなかったため、データベースへのクエリが表示されていますtrue

于 2012-07-05T08:07:02.797 に答える