有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Hibernate注释用于自动增量,但如果在保存之前设置了值,则还应保存该值

我有一个表(PostgreSQL),有两个自动递增字段,第一个用@Id和@GeneratedValue注释,第二个应该自动递增并保存,直到我有意设置它

有没有办法做到这一点

@Entity
@Table(name = "route")
public class Route extends BaseEntity {

 private Integer id;
 private Integer routeNumberId;

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 @Column(name = "id")
 public Integer getId() {
    return id;
 }
 ...
 @XmlAttribute
 @Id
 @Basic(optional = false)
 @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="route_number_seq")
 @GenericGenerator(name="route_number_seq",
                   strategy="com.tripms.models.master.UseIdOrGenerate")
 @Column(name = "route_number_id", nullable = false)
 public Integer getRouteNumberId() {
     return routeNumberId;
 }

}

我不能两次注释@Id,我也不想要复合pk


共 (1) 个答案

  1. # 1 楼答案

    混合使用自动增量和手动值不是一个好主意。当当前序列指向11,但插入了一个值为20的条目时,数据库应该如何运行?一旦序列达到20,您将得到唯一的约束冲突。为了防止这种情况发生,您必须验证生成的序列值是否与任何现有条目冲突——这将导致重试、锁定等一系列其他问题

    重新考虑您的模型或需求可能是一个好主意,为什么要使用第二个伪Id?为什么可以手动和自动填充? 如果您坚持使用此功能,如果您保证手动输入不会与自动生成的输入冲突,则可以使其正常工作。然后,您可以为、、real ID“列(整数ID)创建一个自定义ID生成器,并重写generate方法,以便除了生成ID之外,还可以检查、、pseudo ID”(routeNumberId)的值。如果是null,您可以要求DB从某个序列中给出下一个值。下面是虚拟实现:

    @Override
    public synchronized Serializable generate(SessionImplementor session, Object object) throws HibernateException {
        Serializable result;
        if (object instanceof Route ) {
            Route reoute= ((Route ) object);
            if (route.getid() != null) {
                result = (Serializable) route.getId();
            } else {
                result = <GENERATE new ID(e.g. call super, etc)> ;
            }
            if (route.getRouteNumberId() == null) {
                long autoIncrRouteId = <GENERATE new routeID,>
                route.setRouteNumberId(autoIncrRouteId );
            }
            return result;
        } else {
            result = super.generate(session, object);
        }
    
        return result;
    }
    

    另一个选项是使用@PrePersist entity listener并在那里执行检查和/或序列调用。然而,从监听器访问实体管理器或JPA上下文可能很棘手,因为大多数JPA提供程序不完全支持注入到实体监听器中。您可能需要手动查找jndi,但首先要重新考虑您想要实现的目标是否值得

    编辑:功能Id生成器代码(postgres)

    @Override
    public Serializable generate(SessionImplementor session, Object obj) throws HibernateException {
        Connection connection = session.connection();
        try {
            Route route= ((Route ) obj);
            String seqName = "you_db_id_sequence";
            PreparedStatement ps = connection.prepareStatement("SELECT nextval ('" + seqName + "') as nextval");
            ResultSet rs = ps.executeQuery();
            if (rs.next()) {
                int id = rs.getInt("nextval");
                log.info("Generated order id {} ", id);
                if (route.getRouteNumberId() == null) {
                    route.setrouteNumberid(id); //or call another sequence to get a different id 
                }
                return Long.parseLong(code);
            } else {
               throw new IllegalStateException("could not generate new id");
            }
        } catch (SQLException e) {
            log.error("Could not generate id!", e);
            throw new HibernateException("Unable to generate id from Sequence");
        }
        return null;
    }