缓存不一致 - 实体并不总是保留在缓存的Collection中

时间:2015-06-19 13:54:09

标签: java hibernate jpa caching ehcache

我遇到了Validation实例添加到Step实例的问题。 声明如下:

步骤类:

@Entity
@Table
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Step extends AbstractEntity implements ValidatableStep {

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "step_id", nullable = false)
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    private Set<Validation> validations = new HashSet<>();

    @Override
    public void addValidation(Validation validation) {
      // do some stuff
      ...
      // add validation instance to collection
      getValidations().add(validation);
    }

}

验证类:

@Entity
@Table
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Validation extends AbstractEntity {
  //some properties
}

这两个类都是Cacheable,并应用了READ_WRITE策略。 Validation的单向集合也采用相同的策略进行缓存。

可以预期,当调用addValidation(new Validation('userName'));提交的读写事务时,新的Validation将在后续的只读事务中可见。奇怪的是,有时它确实有效,有时它不起作用......

第一笔交易总是成功;我们看到新的验证存在于数据库中,而Step的版本属性(用于乐观锁定目的)会增加。但有时,第二个读取事务包含一个Step实例,其中包含空Validation集合...

我们的Hibernate缓存配置如下:

hibernate.cache.use_second_level_cache = true
hibernate.cache.use_query_cache = true
hibernate.cache.region.factory_class = org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
hibernate.cache.provider_configuration_file_resource_path = classpath:ehcache.xml
net.sf.ehcache.hibernate.cache_lock_timeout = 10000

知道造成这种奇怪(和随机)行为的原因是什么?

1 个答案:

答案 0 :(得分:1)

Hibernate Collection Cache始终使现有条目无效,并且实体和集合缓存共享相同的AbstractReadWriteEhcacheAccessStrategy,因此更新数据时soft-lock is acquired

因为您使用的是单向一对多关联,所以最终会得到一个 public List<User> UserList = new List<User>(); public MainWindow() { InitializeComponent(); } private void PressedEnter(object sender, KeyEventArgs e) { TextBox CurrentTextbox = (TextBox)sender; if (e.Key == Key.Enter) { switch (CurrentTextbox.Name) { case "EnterName": EnterBirthday.Focus(); break; case "EnterBirthday": EnterEmail.Focus(); break; case "EnterEmail": MainDataGrid.ItemsSource = null; MainDataGrid.ItemsSource = UserList; break; } } } private void AddButton_OnClick(object sender, MouseButtonEventArgs e) { MainDataGrid.ItemsSource = null; MainDataGrid.ItemsSource = UserList; } private List<User> AddItemToGrid() { string[] NameArray = EnterName.Text.Split(' '); string[] BirthdayArray = EnterBirthday.Text.Split('.'); UserList.Add(new User() { FirstName = NameArray[0], LastName = NameArray[1], Birthday = new DateTime(Convert.ToInt16(BirthdayArray[2]), Convert.ToInt16(BirthdayArray[1]), Convert.ToInt16(BirthdayArray[0])), Email = EnterEmail.Text }); return UserList; } 表和一个Step_validation链接表。无论何时添加/删除验证,您都必须点击两个表并且效率较低。

我建议您在public class User { public string FirstName { get; set; } public string LastName { get; set; } public DateTime Birthday { get; set; } public string Email { get; set; } } 实体中添加<Grid> <Grid.RowDefinitions> <RowDefinition Height="30" /> <RowDefinition Height="287*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="235" /> <ColumnDefinition Width="337*" /> </Grid.ColumnDefinitions> <Label Grid.ColumnSpan="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Background="#2196f3" BorderBrush="Transparent" Content="DataGrid" FontFamily="Roboto" FontSize="15" FontWeight="Bold" Foreground="White" /> <StackPanel Grid.Row="1" Grid.Column="0"> <Label Height="25" Margin="10,10,10,0" VerticalAlignment="Top" HorizontalContentAlignment="Center" Background="#2196f3" BorderBrush="Transparent" Content="Name" FontFamily="Roboto" FontSize="13" FontWeight="Bold" Foreground="White" /> <TextBox Name="EnterName" Height="25" Margin="10,5,10,0" VerticalAlignment="Top" HorizontalContentAlignment="Left" VerticalContentAlignment="Center" BorderBrush="#2196f3" FontFamily="Roboto" Foreground="#2196f3" KeyDown="PressedEnter" /> <Label Height="25" Margin="10,10,10,0" VerticalAlignment="Top" HorizontalContentAlignment="Center" Background="#2196f3" BorderBrush="Transparent" Content="Birthday (DD.MM.YYYY)" FontFamily="Roboto" FontSize="13" FontWeight="Bold" Foreground="White" /> <TextBox Name="EnterBirthday" Height="25" Margin="10,5,10,0" VerticalAlignment="Top" HorizontalContentAlignment="Left" VerticalContentAlignment="Center" BorderBrush="#2196f3" FontFamily="Roboto" Foreground="#2196f3" KeyDown="PressedEnter" MaxLength="10" /> <Label Height="25" Margin="10,10,10,0" VerticalAlignment="Top" HorizontalContentAlignment="Center" Background="#2196f3" BorderBrush="Transparent" Content="E-Mail" FontFamily="Roboto" FontSize="13" FontWeight="Bold" Foreground="White" /> <TextBox Name="EnterEmail" Height="25" Margin="10,5,10,0" VerticalAlignment="Top" HorizontalContentAlignment="Left" VerticalContentAlignment="Center" BorderBrush="#2196f3" FontFamily="Roboto" Foreground="#2196f3" KeyDown="PressedEnter" /> <Label Name="AddButton" Height="68" Margin="10,10,10,10" VerticalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Background="#2196f3" BorderBrush="#2196f3" Content="ADD" FontFamily="Roboto" FontSize="30" FontWeight="Bold" Foreground="White" MouseLeftButtonDown="AddButton_OnClick" /> </StackPanel> <DataGrid Name="MainDataGrid" Grid.Row="1" Grid.Column="1" /> </Grid> 一面,并将Validation一面转换为已映射的集合:

@ManyToOne