如何在使用Open-Session in View时避免性能损失?

栏目: 数据库 · 发布时间: 7年前

内容简介:Open-Session In View会在你即使没有使用惰性实体情况下加载且初始化并获取它们,这会导致严重的性能损失。Open-Session in View 反模式在Spring Boot中默认是激活的。如果您更喜欢使用它,那么需要尝试尽可能减轻性能损失:一种优化是将标记Connection设置为只读,这将允许数据库服务器避免写入事务日志;另一个优化包括在您不希望某些实体被懒惰地初始化时,显式明确设置实体。1. application.properties配置:

Open-Session In View会在你即使没有使用惰性实体情况下加载且初始化并获取它们,这会导致严重的性能损失。

Open-Session in View 反模式在Spring Boot中默认是激活的。如果您更喜欢使用它,那么需要尝试尽可能减轻性能损失:一种优化是将标记Connection设置为只读,这将允许数据库服务器避免写入事务日志;另一个优化包括在您不希望某些实体被懒惰地初始化时,显式明确设置实体。

1. application.properties配置:

spring.datasource.url=jdbc:mysql:<font><i>//localhost:3306/db_tennis?createDatabaseIfNotExist=true</i></font><font>
spring.datasource.username=root
spring.datasource.password=root

spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=<b>true</b>

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

spring.datasource.initialization-mode=always
spring.datasource.platform=mysql

# <b>this</b> is <b>default</b> anyway
spring.jpa.open-in-view=<b>true</b>
</font>

2. 父实体Tournament ,注意setXXX方法:

@Entity
<b>public</b> <b>class</b> Tournament implements Serializable {

    <b>private</b> <b>static</b> <b>final</b> <b>long</b> serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    <b>private</b> Long id;

    <b>private</b> String name;

    @OneToMany(cascade = CascadeType.ALL, 
            mappedBy = <font>"tournament"</font><font>, orphanRemoval = <b>true</b>)
    @JsonManagedReference
    <b>private</b> List<TennisPlayer> tennisPlayers = <b>new</b> ArrayList<>();

   </font><font><i>//注意这里,手工明确设置子实体集合</i></font><font>
    <b>public</b> <b>void</b> setTennisPlayers(List<TennisPlayer> tennisPlayers) {
        <b>this</b>.tennisPlayers = tennisPlayers;
    }
}
</font>

子实体TennisPlayer :

@Entity
<b>public</b> <b>class</b> TennisPlayer implements Serializable {

    <b>private</b> <b>static</b> <b>final</b> <b>long</b> serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    <b>private</b> Long id;

    <b>private</b> String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = <font>"tournament_id"</font><font>)
    @JsonBackReference
    <b>private</b> Tournament tournament;

 
}
</font>

3. 获取实体并显式设置惰性属性,通过调用tournament.setTennisPlayers,可以在服务或控制器层中执行此操作,具体取决于它更适合您的情况,但在显式事务之外:

  @RequestMapping(<font>"/tournament_no_players"</font><font>)
    <b>public</b> Tournament tournamentWithoutPlayers() {

        Tournament tournament = tennisService.fetchTournament();
        </font><font><i>// 显式明确设置实体:explicitly set Players of the Tournament</i></font><font>
        </font><font><i>// 为了避免从数据库中获取它们</i></font><font>
        tournament.setTennisPlayers(Collections.emptyList());

        <b>return</b> tournament;
    }
</font>

这为什么有效?为什么我们可以设置托管实体的属性而不触发刷新?那么,答案可以在其文档中找到OpenSessionInViewFilter :

注意:默认情况下,此过滤器不会刷新Hibernate会话,刷新模式设置为FlushMode.NEVER。它假定与关注刷新的服务层事务结合使用:活动事务管理器将临时更改刷新在读写事务期间模式为FlushMode.AUTO,使用刷新模式,在每个事务结束时重置为FlushMode.NEVER。如果您打算在没有事务的情况下使用此过滤器,请考虑更改默认刷新模式(flushMode属性)

下图上面是通过默认OSIV强制加载,结果执行了两条 SQL 语句,它将子实体集合也加载了。下图是使用上面方式之后, 如何在使用Open-Session in View时避免性能损失?


以上所述就是小编给大家介绍的《如何在使用Open-Session in View时避免性能损失?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Data Structures and Algorithms with JavaScript

Data Structures and Algorithms with JavaScript

Michael McMillan / O'Reilly Media / 2014-2-22 / USD 28.51

If you’re using JavaScript on the server-side, you need to implement classic data structures that conventional object-oriented programs (such as C# and Java) provide. This practical book shows you how......一起来看看 《Data Structures and Algorithms with JavaScript》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具