使用Spring Hibernate获取序列的下一个值

10

我正在使用Spring JPA Repository和Hibernate将实体保存到我的Oracle数据库中。如何使用Spring-Hibernate获取我Oracle数据库序列的下一个值?

这是我的Event类:

@Entity
public class Event {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  private Long seriesId;

  private String description;

  public Event() {
  }

  public Long getId() {
    return id;
  }

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

  public Long getSeriesId() {
    return seriesId;
  }

  public void setSeriesId(Long seriesId) {
    this.seriesId = seriesId;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }
}
我需要在事件解析器中为所有事件系列获取序列的下一个值。
public class EventResolver {

    @Autowired
    private EventRepository eventRepository;

    public void createSeriesOfEvents(List<EventAPI> eventsToCreate){

        Long seriesId = null; // TODO: Get the series id from database sequence

        for (EventAPI currEvent : eventsToCreate){
            Event newEvent = new Event();
            newEvent.setDescription(currEvent.description);
            newEvent.setSeriesId(seriesId);
            eventRepository.save(newEvent);
        }

    }
}

感谢任何形式的帮助。


为什么?只需将正确的注释应用于@ID字段,Hibernate就会为您完成所有这些操作。例如,请参见:https://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Sequence_objects http://tech.zooplus.com/sequences-in-hibernate/ - Alan Hay
我希望整个系列(系列可以包含4-5个事件)具有相同的值,因此我无法在创建“Event”实体时生成它。我必须在“createSeriesOfEvents”方法中执行此操作。 - Ron Badur
Spring 5 提供了解决这个问题的新选项。请参见我下面的答案 - Gustavo Passini
4个回答

29

最终我用Spring的方式解决了我的问题,你只需要在JpaRepository中添加一个本地查询,像这样:

public interface EventRepository extends JpaRepository<Event, Long> {

 @Query(value = "SELECT seq_name.nextval FROM dual", nativeQuery = 
        true)
 Long getNextSeriesId();

1
只需要确保查询符合相关数据库的要求。 - ktk
这不会破坏那个东西的意思是,我们使用一个接口,这样Spring可以进行实现,而我们不必担心底层使用的是哪个数据库..?在这种情况下,要切换数据库,我必须重写接口... - tplive
我正在使用Oracle 12c,但是这个查询没有返回任何结果并导致了NullPointerException错误。 - Ashwani Sharma
如何在不使用本地查询的情况下完成?@Ron Badur,我卡在这里,因为我不想使用本地查询。 - KidWithAComputer
你能解释一下你代码中的 Event 对象是什么吗? - aswzen
@aswzen 事件是您正在执行操作的对象。您将使用此存储库查询或保存的对象。 - moolsbytheway

6

3
像这样注释您的id属性:
@Id
@GeneratedValue(generator = "idSequence")
@SequenceGenerator(schema = "MYORASCHEMA", name = "idSequence", sequenceName = "MY_ORACLE_SEQ_NAME", allocationSize = 1)
@Column(name="ID")
private Long id;

我不希望每个对象都拥有自己的ID,我想为所有系列(4-5个Event类型对象)分配相同的系列ID。 - Ron Badur
你的系列数据表是否有父级表? - slambeth
不,我只是想创建一系列事件的选项 - 这意味着具有相同系列ID但不同ID的几个事件。 - Ron Badur
这对我来说是个头疼的问题,所以对于其他人来说:你需要分配大小。原因请参见https://ntsim.uk/posts/how-to-use-hibernate-identifier-sequence-generators-properly。总结:Hibernate使用hi-lo策略获取id,因此如果数据库序列不按50个块分配,则会干扰先前提供的id,并且您将收到约束异常。 - gagarwa
@Ron,你可以使用相同的生成器来解决你的问题。只需使用相同的生成器名称,并在类级别上声明它。你应该能够在其他类中使用它(尽管我还没有确认过)。 - gagarwa

2
你可以在JPA中使用这种方法:
Query q = em.createNativeQuery("select seq_name.nextval from dual");
return (Long)q.getSingleResult();

我从哪里可以获取em对象? - Ron Badur
1
em 表示 EntityManager,您可以使用自动装配进行注入。 - StanislavL

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