【问题标题】:Issue with primary key when try persist entity in the database尝试在数据库中保留实体时出现主键问题
【发布时间】:2014-05-22 21:18:03
【问题描述】:

在我的spring项目中,使用Hibernate处理访问数据库的所有操作,我让系统在数据库中创建表,并在其中插入一些默认值。

作为创建表的基础的实体类的一个示例是:

@Entity
@Table(name="permission")
public class Permissao {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    @Column(name="nome")
    private String nome;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

}

我的问题是,当我尝试通过 Java 代码在已经插入值的表中插入一行时,我收到一条消息说主键已经存在。

我猜这是因为 Hibernate 中的计数器没有用数据库中的计数器更新,但我对这些东西的工作原理还不够了解。

任何人都可以说出发生了什么以及如何解决这个问题?

更新

这就是我在数据库中插入这个实体的地方:

public boolean cadastra(HttpServletRequest request, HttpServletResponse response) {
    String nome_grupo = request.getParameter("nome");
    String[] permissoes = request.getParameterValues("permissoes[]");

    if(nome_grupo == null || permissoes == null)
        return false;

    System.out.println("criando grupo");
    GrupoPermissao grupo = new GrupoPermissao();
    grupo.setNome(nome_grupo);

    System.out.println("adicionando permissoes");
    List<Permissao> lista = new ArrayList<Permissao>();
    for(int i=0; i<permissoes.length; i++)
        lista.add(permissao.findById(Integer.valueOf(permissoes[i]).intValue()));
    grupo.setPermissao(lista);

    System.out.println("salvando no banco de dados");
    boolean result = grupo_permissao.persist(grupo);
    System.out.println("id_grupo = "+grupo.getId());
    return result;
}

这就是上面使用的 GrupoPermissao 实体:

@Entity
@Table(name="role")
public class GrupoPermissao {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    @Column(name="nome")
    private String nome;

    @ManyToMany
    @JoinTable(name="role_permissions", joinColumns={@JoinColumn(name="fk_role")}, inverseJoinColumns={@JoinColumn(name="fk_permission")})
    @LazyCollection(LazyCollectionOption.FALSE)
    private List<Permissao> permissao = new ArrayList<Permissao>();

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public List<Permissao> getPermissao() {
        return permissao;
    }

    public void setPermissao(List<Permissao> permissao) {
        this.permissao = permissao;
    }

}

【问题讨论】:

    标签: java spring hibernate


    【解决方案1】:

    您可以在创建对象 Permissao 时插入 id 属性。没必要。

    【讨论】:

    • 我更新了我的问题以包含我插入的代码。我猜我不会在任何地方插入 id 属性。
    【解决方案2】:

    这里的问题可能是您将 id 声明为原语而不是包装器。

    所以而不是:

    private int id;
    

    你应该有:

    private Integer id;
    

    当您创建组时:

    GrupoPermissao grupo = new GrupoPermissao();
    

    id为0,与NULL不同。

    所以调用此方法的两个请求将尝试设置 id 为 0 的组,所以你有冲突。

    只有当id为NULL时,AUTO生成策略才会让数据库设置id。

    而且 Hibernate 不使用 AUTO 策略存储任何 id 计数器,而是将此责任委托给数据库。

    【讨论】:

    • 我更新了我的代码以将我的 Id 更改为 Integer,但仍然有同样的问题(顺便说一下,实体没有用 0 初始化,而是用数字序列中的最后一个数字- 最后一个数字是 9 - ,这与我通过程序插入的元素数量相匹配,因为我认为 Hibernate 有自己的计数器)。
    • 还有一件事,你在 GrupoPermissao 上调用persist,但它没有任何级联到私有列表 permissao。
    【解决方案3】:

    好的,我终于解决了这个问题。问题是用于填充数据库的文件正在使用带有主键指示的 INSERT。我删除了这个引用,让 hibernate 处理这个问题,现在一切正常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-28
      • 2017-02-04
      • 1970-01-01
      • 1970-01-01
      • 2016-11-01
      • 2016-03-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多