使用Grails的Hibernate和PostgreSQL

6

有一个简单的方法可以设置Hibernate在使用PostgreSQL时为每个表使用不同的主键ID吗? 我尝试在DataSource中使用PostgreSQL方言:

dialect = org.hibernate.dialect.PostgreSQLDialect 
or
dialect = net.sf.hibernate.dialect.PostgreSQLDialect

但它不起作用。 谢谢。
1个回答

13

简而言之,没有一种简单的方法可以做到这一点。不过,我已经找到了一个解决方案,它确实有效。基本上,你需要实现一个自定义方言。以下是一个实现示例(请注意,在注释中提供了实现的原始来源)。

package com.my.custom;

import java.util.Properties;

import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.SequenceGenerator;
import org.hibernate.type.Type;


/**
 * Creates a sequence per table instead of the default behavior of one sequence.
 *
 * From <a href='http://www.hibernate.org/296.html'>http://www.hibernate.org/296.html</a>
 * @author Burt
 */
public class TableNameSequencePostgresDialect extends PostgreSQLDialect {

    /**
     * Get the native identifier generator class.
     * @return TableNameSequenceGenerator.
     */
    @Override
    public Class<?> getNativeIdentifierGeneratorClass() {
            return TableNameSequenceGenerator.class;
    }

    /**
     * Creates a sequence per table instead of the default behavior of one sequence.
     */
    public static class TableNameSequenceGenerator
           extends SequenceGenerator {

            /**
             * {@inheritDoc}
             * If the parameters do not contain a {@link SequenceGenerator#SEQUENCE} name, we
             * assign one based on the table name.
             */
            @Override
            public void configure(
                            final Type type,
                            final Properties params,
                            final Dialect dialect) {
                    if (params.getProperty(SEQUENCE) == null
                                    || params.getProperty(SEQUENCE).length() == 0) {
                            String tableName = params.getProperty(PersistentIdentifierGenerator.TABLE);
                            if (tableName != null) {
                                    params.setProperty(SEQUENCE, "seq_" + tableName);
                            }
                    }
                    super.configure(type, params, dialect);
            }
    }

}
上述实现应该被保存为TableNameSequencePostgresDialect.java,存储在Grails项目的src/java/com/my/custom目录下。
接下来,更新你的DataSource.groovy文件,使用这个新的自定义方言。
dialect = com.my.custom.TableNameSequencePostgresDialect

基本上就是这样了。虽然不< b >容易,但是可以做到。


不客气。我自己花了很多时间研究这个问题,很失望最终只能采用自定义实现的方法。但是,就像你说的那样,它确实有效。 :) - Joshua Moore
5
这是在http://grails.1312388.n4.nabble.com/One-hibernate-sequence-is-used-for-all-Postgres-tables-td1351722.html找到的内容。 - Burt Beckwith
@BurtBeckwith 为什么我不惊讶你会想到这个?你太棒了。谢谢! - Joshua Moore
我在搜索了很多后来到这里,但是上面的代码并没有解决我的问题,我仍然收到错误信息“插入失败 - 违反主键约束”,我正在使用PostgreSQL。请帮我纠正这个问题。 - Saurabh Mishra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接