【问题标题】:Manage a composite primary key with an incremental id using JPA and Oracle使用 JPA 和 Oracle 管理具有增量 id 的复合主键
【发布时间】:2012-10-15 10:38:04
【问题描述】:

使用 JPA,我尝试修改多语言内容的持久对象,这意味着我需要一个复合键,带有 id 和语言。 id 还需要使用序列递增(我使用的是 Oracle)。怎么办?

目前,我得到了一个 Contenu 课程:

@Entity
@Table(name = "CONTENUS")
public class Contenus implements java.io.Serializable {

    private ContenusId id;
    ...
}

还有一个 ContenusId 类:

@Embeddable
public class ContenusId implements java.io.Serializable {

    private Long id;
    private String langue;
    ...
}

但这不处理增量 id。有什么想法吗?

【问题讨论】:

    标签: java oracle jpa sequence composite-key


    【解决方案1】:

    首先,您需要为 JPA 实体管理器创建 ID 类,以了解如何检查两个对象是否相等。此 ID 类应覆盖 equals()hashcode() 方法。

    /**
     * ContenusPK.java
     * 
     * $Source$
     */
    import java.io.Serializable;
    
    public class ContenusPK implements Serializable
    {
        public static final long serialVersionUID = 1L;
    
        private Long id;
        private String langue;
    
        /*
         * (non-Javadoc)
         * @see java.lang.Object#hashCode()
         */
        @Override
        public int hashCode()
        {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((id == null) ? 0 : id.hashCode());
            result = prime * result + ((langue == null) ? 0 : langue.hashCode());
            return result;
        }
    
        /*
         * (non-Javadoc)
         * @see java.lang.Object#equals(java.lang.Object)
         */
        @Override
        public boolean equals(Object obj)
        {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            ContenusPK other = (ContenusPK) obj;
            if (id == null)
            {
                if (other.id != null)
                    return false;
            }
            else if (!id.equals(other.id))
                return false;
            if (langue == null)
            {
                if (other.langue != null)
                    return false;
            }
            else if (!langue.equals(other.langue))
                return false;
            return true;
        }
    
        /**
         * @return the serialversionuid
         */
        public static long getSerialversionuid()
        {
            return serialVersionUID;
        }
    
        /**
         * @return the id
         */
        public Long getId()
        {
            return id;
        }
    
        /**
         * @return the langue
         */
        public String getLangue()
        {
            return langue;
        }
    
        /**
         * @param id the id to set
         */
        protected void setId(Long id)
        {
            this.id = id;
        }
    
        /**
         * @param langue the langue to set
         */
        protected void setLangue(String langue)
        {
            this.langue = langue;
        }
    
    }
    

    然后你需要声明你的实体的复合主键属性,将ID类与实体关联,并定义ID​​生成策略,如下:

    @IdClass(ContenusPK.class)
    @Entity
    @TableName(name="")
    public class Contenus {
    
        @Id
        @GeneratedValue(
            strategy = GenerationType.SEQUENCE, 
            generator = "GENERATOR_NAME")
        @SequenceGenerator(
            name = "GENERATOR_NAME", 
            sequenceName = "SEQUENCE NAME IN DB")
        @Column(name = "CONTENUS_ID")
        private Long id;
    
        @Id
        @Column(name = "LANGUE")
        private String langue;
    
        ...
    }
    

    【讨论】:

    • 那么,如果我创建了 3 个 Contenus 对象,其语言值为“en”、“fr”和“de”,然后我调用 myEntityManager.persist();,这 3 个对象会以相同的 id 值保存吗?
    • 不,序列会为每条记录生成不同的 ID。
    • 我认为这就是亚历克西斯试图避免的。由于它是一个复合键,因此应该有一种方法可以仅在需要时使用下一个序列值。应该可以手动使用下一个序列号,因此可以决定何时必须增加 id。
    猜你喜欢
    • 1970-01-01
    • 2020-02-19
    • 1970-01-01
    • 2021-10-07
    • 2018-02-02
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多