Java 基于外键的增量字段(JPA、Hibernate、Oracle DB)
是否可以基于外键自动增加字段?我希望通过JPA(Hibernate)和Oracle DB实现这一点。我已经读过,使用Java 基于外键的增量字段(JPA、Hibernate、Oracle DB),java,oracle,hibernate,jpa,Java,Oracle,Hibernate,Jpa,是否可以基于外键自动增加字段?我希望通过JPA(Hibernate)和Oracle DB实现这一点。我已经读过,使用MySQL的InnoDB引擎是不可能的 这很像下面的问题: 但是这些仅仅基于MySQL表本身。不是JPA和Oracle DB 这正是我需要的,但遗憾的是没有答案 作为一个具体的例子,考虑一个简单的例子。每个学生都有多本书。Book有一个主键(常规增量),但也有一个followUpNumber。该数字从1开始,并自动递增,每次将书籍添加到学生。这意味着每个学生都有一个书
MySQL
的InnoDB
引擎是不可能的
这很像下面的问题:
作为一个具体的例子,考虑一个简单的例子。每个学生都有多本书。
Book
有一个主键(常规增量),但也有一个followUpNumber
。该数字从1开始,并自动递增,每次将书籍添加到学生。这意味着每个学生
都有一个书籍
列表,其中后续编号每次从1开始。下面是书
表,显示我的意思:
|------|------------|-----------------|
| id | student_id | followup_number |
|------|------------|-----------------|
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 1 |
| 5 | 1 | 4 |
| 6 | 1 | 5 |
| 7 | 2 | 2 |
| 8 | 3 | 1 |
| 9 | 3 | 2 |
|------|------------|-----------------|
- id是主键
- 学生id是学生的外键
- followup\u number是每个学生id从1开始的字段
是否存在不需要放置在主键字段上的自定义策略?我当前的解决方案是在添加一本新书之前,迭代所有的新书,获得最高的后续编号,并将该编号+1分配给新书。但我觉得必须有一种更干净、更优雅的方法来做到这一点。可以使用注释
public@interface-OrderColumn
指定一列,该列用于
保持列表的持久顺序。持久性提供程序是
负责在检索时维护订单,并在
数据库持久性提供程序负责更新
刷新数据库以反映任何插入时进行排序,
影响列表的删除或重新排序
OrderColumn注释是在OneToMany或ManyToMany上指定的
元素集合上的关系或。OrderColumn注释
在引用的关系的一侧指定
要订购的集合。“订单”列不可见
实体或可嵌入类状态的一部分
OrderBy注释应用于显示为的排序
持久状态,并由应用程序维护。勤务员
指定OrderColumn时不使用注释
订单列必须为整型。持久性提供者
维护的值的连续(非稀疏)顺序
更新关联或元素集合时的顺序列。这个
第一个元素的order列值为0
唯一的缺点是第一个元素的数字是0,而不是1
例如:
@Entity
@Table(name="STUDENT")
@SequenceGenerator(name="student_seq", initialValue=1,
allocationSize=10,sequenceName="STUDDENT_SEQ")
public class Student {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="student_seq")
private Long Id;
@Column(name="NAME")
private String name;
@OneToMany(cascade = CascadeType.ALL, mappedBy="student")
@OrderColumn(name="FOLLOWUP_NUMBER")
private List<Book> books = new ArrayList<>();
...............
...............
}
这个简单的测试用例:
EntityTransaction tr = em.getTransaction();
tr.begin();
for (int j = 1; j < 10; j++) {
Student student = new Student("Student name " + j);
for (int i = 1; i <= 10; i++) {
student.getBooks().add(new Book("Some book" + i, student));
}
em.persist(student);
}
tr.commit();
Query query = em.createQuery(
"Select b FROM Book b JOIN b.student s " +
"WHERE s.name = :studentname AND b.followUpNumber = :follownbr"
);
query.setParameter("studentname", "Student name 6");
query.setParameter("follownbr", Long.valueOf(4));
Book book = (Book)query.getSingleResult();
System.out.println("Found book = " + book.getTitle());
System.out.println("book follow nbr= " + book.getFollowUpNumber());
性能可能是另一个缺点,因为对于每本书,Hibernate都会生成两个SQL命令—一个insert,然后更新FOLLOWUP\u NUMBER
列。
更糟糕的是,当某本书被删除时,然后Hibernate再次为给定的学生生成所有数字,并为所有剩余的书籍触发FOLLOWUP\u NUMBER
列的更新
编辑
但令我烦恼的是“订单列作为订单的一部分不可见”
实体或可嵌入类的状态。“。数据和我想的一样
就像在数据库中一样,但它不会反映到我的实体上。当我
我想利用这个跟进号码
我不知道这在JPA中是否可行,但在这种情况下可以使用Hibernate扩展@Formula
:
class Book{
.......
.......
@Formula(value="FOLLOWUP_NUMBER")
private Long followUpNumber;
public Long getFollowUpNumber() {
return followUpNumber;
}
........
........
}
甚至可以查询此计算字段,例如下面的测试用例:
EntityTransaction tr = em.getTransaction();
tr.begin();
for (int j = 1; j < 10; j++) {
Student student = new Student("Student name " + j);
for (int i = 1; i <= 10; i++) {
student.getBooks().add(new Book("Some book" + i, student));
}
em.persist(student);
}
tr.commit();
Query query = em.createQuery(
"Select b FROM Book b JOIN b.student s " +
"WHERE s.name = :studentname AND b.followUpNumber = :follownbr"
);
query.setParameter("studentname", "Student name 6");
query.setParameter("follownbr", Long.valueOf(4));
Book book = (Book)query.getSingleResult();
System.out.println("Found book = " + book.getTitle());
System.out.println("book follow nbr= " + book.getFollowUpNumber());
给出以下结果:
Found book = Some book5
book follow nbr= 4
Hibernate使用以下SQL查找该书:
select
book0_.id as id1_0_,
book0_.STUDENT_ID as STUDENT_ID3_0_,
book0_.TITLE as TITLE2_0_,
book0_.FOLLOWUP_NUMBER as formula0_
from
Book book0_
inner join
STUDENT student1_
on book0_.STUDENT_ID=student1_.Id
where
student1_.NAME=?
and book0_.FOLLOWUP_NUMBER=?
我想到了insert上的数据库触发器,它不需要由JPA解决。但我很想看到面向JPA的解决方案。很高兴看到JPA有一个可能的解决方案。但困扰我的是“order列作为实体或可嵌入类的状态的一部分是不可见的”。数据就像我希望它在数据库中一样,但它没有反映到我的实体上。虽然我想利用这个FOLLOWUP\u NUMBER
@Formula
扩展可以用于这种情况,但我在答案后面附加了一个示例。
select
book0_.id as id1_0_,
book0_.STUDENT_ID as STUDENT_ID3_0_,
book0_.TITLE as TITLE2_0_,
book0_.FOLLOWUP_NUMBER as formula0_
from
Book book0_
inner join
STUDENT student1_
on book0_.STUDENT_ID=student1_.Id
where
student1_.NAME=?
and book0_.FOLLOWUP_NUMBER=?