如何从“0”开始 UNSIGNED AUTO_INCREMENT 字段?

Posted

技术标签:

【中文标题】如何从“0”开始 UNSIGNED AUTO_INCREMENT 字段?【英文标题】:how to start from "0" an UNSIGNED AUTO_INCREMENT field? 【发布时间】:2012-03-14 18:43:03 【问题描述】:

我有以下表格:

其中idclientunsigned auto_increment

客户实体的代码:

import java.io.Serializable;

import java.util.List;

import javax.persistence.*;

import javax.xml.bind.annotation.XmlRootElement;

import javax.xml.bind.annotation.XmlTransient;


@Entity
@Table(name = "CLIENT", catalog = "TEST", schema = "PUBLIC")
@XmlRootElement
@NamedQueries(
@NamedQuery(name = "Client.findAll", query = "SELECT c FROM Client c"),
@NamedQuery(name = "Client.findByIdclient", query = "SELECT c FROM Client c WHERE c.idclient = :idclient"),
@NamedQuery(name = "Client.findByLibel", query = "SELECT c FROM Client c WHERE c.libel = :libel"),
@NamedQuery(name = "Client.findByAdresse", query = "SELECT c FROM Client c WHERE c.adresse = :adresse"),
@NamedQuery(name = "Client.findByNomResp", query = "SELECT c FROM Client c WHERE c.nomResp = :nomResp"),
@NamedQuery(name = "Client.findByTelPortable", query = "SELECT c FROM Client c WHERE c.telPortable = :telPortable"),
@NamedQuery(name = "Client.findByTelFixe", query = "SELECT c FROM Client c WHERE c.telFixe = :telFixe"),
@NamedQuery(name = "Client.findByFax", query = "SELECT c FROM Client c WHERE c.fax = :fax"),
@NamedQuery(name = "Client.findByCodeTva", query = "SELECT c FROM Client c WHERE c.codeTva = :codeTva"),
@NamedQuery(name = "Client.findByCodeExo", query = "SELECT c FROM Client c WHERE c.codeExo = :codeExo"),
@NamedQuery(name = "Client.findByBanque", query = "SELECT c FROM Client c WHERE c.banque = :banque"),
@NamedQuery(name = "Client.findByRib", query = "SELECT c FROM Client c WHERE c.rib = :rib"),
@NamedQuery(name = "Client.findByCredit", query = "SELECT c FROM Client c WHERE c.credit = :credit"),
@NamedQuery(name = "Client.findByEchance", query = "SELECT c FROM Client c WHERE c.echance = :echance"),
@NamedQuery(name = "Client.findByMail", query = "SELECT c FROM Client c WHERE c.mail = :mail"),
@NamedQuery(name = "Client.findByEtat", query = "SELECT c FROM Client c WHERE c.etat = :etat"))
public class Client implements Serializable 
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "IDCLIENT", nullable = false)
private Integer idclient;
@Basic(optional = false)
@Column(name = "LIBEL", nullable = false, length = 100)
private String libel;
@Basic(optional = false)
@Column(name = "ADRESSE", nullable = false, length = 100)
private String adresse;
@Basic(optional = false)
@Column(name = "NOM_RESP", nullable = false, length = 60)
private String nomResp;
@Basic(optional = false)
@Column(name = "TEL_PORTABLE", nullable = false, length = 16)
private String telPortable;
@Basic(optional = false)
@Column(name = "TEL_FIXE", nullable = false, length = 16)
private String telFixe;
@Basic(optional = false)
@Column(name = "FAX", nullable = false, length = 16)
private String fax;
@Basic(optional = false)
@Column(name = "CODE_TVA", nullable = false, length = 30)
private String codeTva;
@Basic(optional = false)
@Column(name = "CODE_EXO", nullable = false, length = 30)
private String codeExo;
@Basic(optional = false)
@Column(name = "BANQUE", nullable = false, length = 60)
private String banque;
@Basic(optional = false)
@Column(name = "RIB", nullable = false, length = 22)
private String rib;
@Basic(optional = false)
@Column(name = "CREDIT", nullable = false)
private double credit;
@Basic(optional = false)
@Column(name = "ECHANCE", nullable = false)
private int echance;
@Basic(optional = false)
@Column(name = "MAIL", nullable = false, length = 70)
private String mail;
@Basic(optional = false)
@Column(name = "ETAT", nullable = false)
private char etat;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "clientIdclient")
private List<Facture> factureList;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "clientIdclient")
private List<FactProforma> factProformaList;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "clientIdclient")
private List<Bl> blList;

public Client() 


public Client(Integer idclient) 
    this.idclient = idclient;


public Client(Integer idclient, String libel, String adresse, String nomResp, String telPortable, String telFixe, String fax, String codeTva, String codeExo, String banque, String rib, double credit, int echance, String mail, char etat) 
    this.idclient = idclient;
    this.libel = libel;
    this.adresse = adresse;
    this.nomResp = nomResp;
    this.telPortable = telPortable;
    this.telFixe = telFixe;
    this.fax = fax;
    this.codeTva = codeTva;
    this.codeExo = codeExo;
    this.banque = banque;
    this.rib = rib;
    this.credit = credit;
    this.echance = echance;
    this.mail = mail;
    this.etat = etat;


public Integer getIdclient() 
    return idclient;


public void setIdclient(Integer idclient) 
    this.idclient = idclient;


public String getLibel() 
    return libel;


public void setLibel(String libel) 
    this.libel = libel;


public String getAdresse() 
    return adresse;


public void setAdresse(String adresse) 
    this.adresse = adresse;


public String getNomResp() 
    return nomResp;


public void setNomResp(String nomResp) 
    this.nomResp = nomResp;


public String getTelPortable() 
    return telPortable;


public void setTelPortable(String telPortable) 
    this.telPortable = telPortable;


public String getTelFixe() 
    return telFixe;


public void setTelFixe(String telFixe) 
    this.telFixe = telFixe;


public String getFax() 
    return fax;


public void setFax(String fax) 
    this.fax = fax;


public String getCodeTva() 
    return codeTva;


public void setCodeTva(String codeTva) 
    this.codeTva = codeTva;


public String getCodeExo() 
    return codeExo;


public void setCodeExo(String codeExo) 
    this.codeExo = codeExo;


public String getBanque() 
    return banque;


public void setBanque(String banque) 
    this.banque = banque;


public String getRib() 
    return rib;


public void setRib(String rib) 
    this.rib = rib;


public double getCredit() 
    return credit;


public void setCredit(double credit) 
    this.credit = credit;


public int getEchance() 
    return echance;


public void setEchance(int echance) 
    this.echance = echance;


public String getMail() 
    return mail;


public void setMail(String mail) 
    this.mail = mail;


public char getEtat() 
    return etat;


public void setEtat(char etat) 
    this.etat = etat;


@XmlTransient
public List<Facture> getFactureList() 
    return factureList;


public void setFactureList(List<Facture> factureList) 
    this.factureList = factureList;


@XmlTransient
public List<FactProforma> getFactProformaList() 
    return factProformaList;


public void setFactProformaList(List<FactProforma> factProformaList) 
    this.factProformaList = factProformaList;


@XmlTransient
public List<Bl> getBlList() 
    return blList;


public void setBlList(List<Bl> blList) 
    this.blList = blList;


@Override
public int hashCode() 
    int hash = 0;
    hash += (idclient != null ? idclient.hashCode() : 0);
    return hash;


@Override
public boolean equals(Object object) 
    // TODO: Warning - this method won't work in the case the id fields are not set
    if (!(object instanceof Client)) 
        return false;
    
    Client other = (Client) object;
    if ((this.idclient == null && other.idclient != null) || (this.idclient != null && !this.idclient.equals(other.idclient))) 
        return false;
    
    return true;


@Override
public String toString() 
    return "glob.entitys.Client[ idclient=" + idclient + " ]";
  


当我尝试在数据库中插入一行时:

Utilisateur user=new Utilisateur(loginActuel);
Client client=new Client(0);// the error comes from here
Facture fact=new Facture(null,new Date());
fact.setClientIdclient(client);
fact.setUtilisateurLogin(user);
FactureJpaController fjc=new FactureJpaController(emf);
fjc.create(fact);

我收到了这个丑陋的错误(但是当我设置 new Client(1) 时效果很好):

Exception in thread "AWT-EventQueue-0" javax.persistence.RollbackException: Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.ValidationException

Exception Description: Null or zero primary key encountered in unit of work clone [glob.entitys.Client[ idclient=0 ]], primary key [0]. Set descriptors IdValidation or the "eclipselink.id-validation" property.

如何解决这个问题?

备注:客户端 idclient = 0 已插入数据库(但手动插入) 我想一劳永逸地克服这个“问题”,如何防止JPA或H2数据库从0开始?

【问题讨论】:

【参考方案1】:

H2 允许使用0 作为主键。错误消息并非来自 H2。

但是,在我看来,EclipseLink 的某些(旧?)版本不允许使用0

客户端 idclient = 0 已插入数据库

此版本的 EclipseLink 似乎不支持此功能。看起来可以解决这个问题,你不应该使用值0

【讨论】:

是的,正如他所说,Mikko Maunu JPA 不支持零值作为主键,谢谢您的澄清 JPA 规范支持 0 作为主键。旧版本的 EclipseLink 作为实现之一不支持,这是 EclipseLink 中报告的错误。 更新了我的回答,说“旧版本的 EclipseLink 不支持 0 作为主键值”而不是“JPA 规范不支持它”。 如错误状态,允许0,设置“eclipselink.id-validation”属性。【参考方案2】:

有两种方法可以在 Eclipselink 中允许主键中的零:

persistence.xml中的参数:

<property name="eclipselink.id-validation" value="NULL"/>

PrimaryKey 相关实体类的注解:

@PrimaryKey(validation = IdValidation.NULL)

【讨论】:

【参考方案3】:

对于 id 具有(或负)值的 JPA(规范 2.0)是可以的。也可以作为 H2 的主键值。

EclipseLink 的旧版本确实将值 0 或更小的值视为无效的主键。参见以下示例:Bug 249948。因此更新 EclipseLink 会有所帮助。

顺便问一下,为什么要在构造函数中设置应该生成的 idclient 值?

【讨论】:

感谢链接,只是实体 Facture 必须使用客户端实体的实例( fact.setClientIdclient(client); )...【参考方案4】:

我遇到了这个错误,在我的 jpa 身份中添加以下注释解决了它:

  @Column(name = "ID_SEARCH_LOG", nullable = false, insertable = true, updatable = true, length = 10, precision = 0)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int idSearchLog;

【讨论】:

【参考方案5】:

文档说

默认情况下,对于不能为 null 的基本类型(例如 int 和 long),EclipseLink 将零解释为 null,从而导致零成为主键的无效值。

但也可以在 persistence.xml 或特定实体中更改此行为。

http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Entities/Ids/Id#Allowing_Zero_Value_Primary_Keys

【讨论】:

以上是关于如何从“0”开始 UNSIGNED AUTO_INCREMENT 字段?的主要内容,如果未能解决你的问题,请参考以下文章

unsigned和signed char

MySQL 表设计案例

C语言中的unsigned int是啥

c++中定义一个buff为unsigned char 型,如何初始化全为0

unsigned 变量为啥不能和0进行比较

在“for”循环中运行整个“unsigned char”范围