使用PostgreSQL,为什么不Hibernate / JPA创建级联约束? [英] Using PostgreSQL, why doesn't Hibernate/JPA create cascade constraints?

查看:189
本文介绍了使用PostgreSQL,为什么不Hibernate / JPA创建级联约束?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实体 Bar

  @OneToMany = CascadeType.ALL,mappedBy =bar)
private Set< Foo> fooSet;

实体 Foo

  @ManyToOne(可选= false)
@JoinColumn(name =bar_id)
私人酒吧;

Hibernate在foo.bar - > bar.id上创建外键约束,但是它没有指定 ON DELETE CASCADE 。为什么不?还有什么办法可以实现吗?

或者我可以在DB中手动添加 ON DELETE CASCADE 并禁用DDL代),这是一个很好的做法而且,我必须以某种方式修改我的代码让Hibernate知道相关记录被数据库自动删除吗?


$ b

谢谢

更新 - 这是我的JPA / Hibernate / PostgreSQL配置:

 < bean id =dataSourceclass =org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy> 
< constructor-arg>
< bean class =org.springframework.jdbc.datasource.DriverManagerDataSource>
< property name =driverClassNamevalue =org.postgresql.Driver/>
< property name =usernamevalue =my_username/>
< property name =passwordvalue =my_password/>
< / bean>
< / constructor-arg>
< / bean>
< bean id =jpaAdapterclass =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter>
< property name =databasePlatformvalue =org.hibernate.dialect.PostgreSQLDialect/>
< property name =showSqlvalue =true/>
< property name =generateDdlvalue =true/>
< / bean>
< bean id =entityManagerFactoryclass =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean>
< property name =jpaVendorAdapterref =jpaAdapter/>
< property name =jpaProperties>
<道具>
< prop key =hibernate.format_sql> true< / prop>
< prop key =hibernate.hbm2ddl.auto> update< / prop>
< /道具>
< / property>
< property name =dataSourceref =dataSource/>
< / bean>

更新2 - 澄清了我的意思:创建外键约束,但我想知道为什么它没有指定 ON DELETE CASCADE (相应地改变了原来的问题)

解决方案

Hibernate手动管理级联操作本身。更重要的是,如果你要在数据库上进行级联,而不是在Hibernate中声明它们(对于性能问题),在某些情况下你可能会得到错误。这是因为Hibernate将实体存储在会话缓存中,所以它不知道数据库级联中删除的东西。当你使用二级缓存的时候,你的情况会更糟,因为这个缓存的存活时间比会话长,而db端的这种改变对于其他会话是不可见的,因为我已经读了一下Hibernate的源代码(真是令人不愉快的经历),我怀疑在任何情况下都可以管理级联数据库方面 - Hibernate设计所做的假设太多,与数据库实际情况不兼容。


I have an entity Bar:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "bar")
private Set<Foo> fooSet;

And an entity Foo:

@ManyToOne(optional = false)
@JoinColumn(name = "bar_id")
private Bar bar;

Hibernate creates the foreign key constraint on foo.bar -> bar.id but it doesnt specify ON DELETE CASCADE. Why not? And is there any ways to achieve it?

Alternatively I can add the ON DELETE CASCADE manually in the DB (and disable DDL generation), is this a good practice? And also, do I have to modify my code in some way to let Hibernate know that related records are deleted automatically by the database?

Thanks.

Update - this is my JPA/Hibernate/PostgreSQL configuration:

<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
    <constructor-arg>
        <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="org.postgresql.Driver" />
            <property name="url" value="jdbc:postgresql://localhost:5432/my_db" />
            <property name="username" value="my_username" />
            <property name="password" value="my_password" />
        </bean>
    </constructor-arg>
</bean>
<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
    <property name="showSql" value="true" />
    <property name="generateDdl" value="true" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jpaVendorAdapter" ref="jpaAdapter" />
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
    <property name="dataSource" ref="dataSource" />
</bean>

Update 2 - clarified what I mean: the foreign key constraint is created, but I'm wondering why it doesnt specify ON DELETE CASCADE (changed the original question accordingly)

解决方案

Hibernate manages cascade operations itself manually. What is more, if you would make cascades on database, and not declare them in Hibernate (for performance issues) you could in some circumstances get errors. This is because Hibernate stores entities in its session cache, so it would not know about database deleting something in cascade.

When you use second-level cache, your situation is even worse, because this cache lives longer than session and such changes on db-side will be invisible to other sessions as long old values are stored in this cache.

I've read a bit Hibernate sources (really unpleasant experience) and I doubt it is under any circumstances possible to manage cascades on database side - there are too many assumptions made by Hibernate design that are incompatibile with DB reality.

这篇关于使用PostgreSQL,为什么不Hibernate / JPA创建级联约束?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆