跨Web请求管理持久用户的数据

时间:2012-07-04 09:42:56

标签: hibernate persistence jpa-2.0

我正在使用用户身份验证的WebSocket服务器。我现在不知道如何在请求中存储此用户。我的WebSocket连接可能会保持打开几个小时,有时它会每分钟收到100个请求,有时每小时只收到2个请求(这是不可预测的)。用户数据可能会被另一个应用程序更改,这不是我的问题,但它可能是相关的。我正在使用spring 3和hibernate 3.6.9。

我的问题是:我应该使用特定的事务管理吗?如何管理这些用户数据。

我测试了2个用例:

1。 在登录时加载我的用户实体并在每个请求中合并()它。我必须合并它,因为事务在每个请求后关闭。合并不是一个好的解决方案,因为它不加载数据库实体,而是保留合并的实体。因此,如果数据在其他地方更新,它将还原它们而不加载更新的数据。

2。 在登录时,我只存储用户ID,并在每次请求时查找()我的用户。为了避免数据库请求泛滥,我设置了第二级缓存,但根据我的sql server log 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的方法。

1 个答案:

答案 0 :(得分:1)

你的第二个解决方案看起来很明显。您正在查看对数据库的查询,因为您未将hibernate.cache.use_second_level_cache属性设置为true