2011-02-10 29 views
19

Tôi có một loại bản đồ kỳ lạ cho một lĩnh vực:Chỉ định tên ràng buộc khoá ngoại khi sử dụng Bản đồ và @ElementCollection với Hibernate

@ElementCollection 
@CollectionTable(name = "studentGradeLevel", joinColumns = @JoinColumn(name = "studentId")) 
@MapKeyJoinColumn(name = "schoolYearId") 
@Column(name = "gradeLevel", nullable = false) 
@ForeignKey(name = "fkStudentGrade2Student") 
private Map<SchoolYear, GradeLevel> gradeLevels; 

năm học là một thực thể và GradeLevel là một enum.

Tôi đang sử dụng các công cụ Hibernate để tạo DDL cho lược đồ. Giản đồ rằng đây là tạo ra dưới đây:

create table studentGradeLevel (
    studentId numeric(19,0) not null, 
    gradeLevel int not null, 
    schoolYearId int not null, 
    primary key (studentId, schoolYearId) 
); 

alter table studentGradeLevel 
    add constraint FK1BCA4A883A97C498 
    foreign key (schoolYearId) 
    references schoolYear; 

alter table studentGradeLevel 
    add constraint fkStudentGrade2Student 
    foreign key (studentId) 
    references student; 

Vấn đề là tôi dường như không thể thay đổi tên hạn chế cho chính nước ngoài giữa các bảng thu thập và bảng cho các đơn vị sử dụng làm khóa bản đồ.

Tôi đã sử dụng @ForeignKey để chỉ định các tên ràng buộc cho @OneToMany, @ManyToMany và @ElementCollections khác không có vấn đề gì. Tôi đã thử thuộc tính "inverseName" của ForiegnKey nhưng dường như nó bị bỏ qua. @MapKeyJoinColumn dường như không có bất kỳ thuộc tính nào có thể ảnh hưởng đến điều này.

Có ai biết nếu có cách nào để thực hiện việc này không?

+1

Ý của bạn là 'FK1BCA4A883A97C498'? Tại sao bạn muốn quản lý tên này. –

+2

Có. Lý do là nếu ràng buộc bị vi phạm thì lỗi được trả về sẽ chứa một tên có ý nghĩa. –

+0

Ai đó đã mở một vé ngay tại đây: http://opensource.atlassian.com/projects/hibernate/browse/HCANN-24. Bạn có thể muốn bỏ phiếu để các nhà phát triển Hibernate biết tầm quan trọng của việc sửa lỗi này. – limc

Trả lời

0

Tôi đã có cùng một vấn đề và bởi vì tôi không thể tìm thấy một cách để làm điều đó kết thúc lên truy vấn cơ sở dữ liệu chính nó để có được thông tin đó.

Chạy truy vấn này trên SQL SERVER tên

select kcu.TABLE_NAME, kcu.CONSTRAINT_NAME, tc.CONSTRAINT_TYPE, kcu.COLUMN_NAME 
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc 
join INFORMATION_SCHEMA.KEY_COLUMN_USAGE as kcu 
on kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA 
and kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME 
and kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA 
and kcu.TABLE_NAME = tc.TABLE_NAME 

Bạn sẽ nhận được tablename, tên hạn chế (như FK1BCA4A883A97C498), gõ (như hạn chế UNIQUE) và cột. Điều đó sẽ đủ để trả về một thông báo lỗi có ý nghĩa.

tôi biết là không tuyệt vời vì bạn mất tính di động db nhưng dường như không có cách nào để làm những gì bạn đang yêu cầu vào lúc này ...

6

tôi phải vá Hibernate để tạo ra tên chính nước ngoài khác nhau, bởi vì những cái mà Hibernate tạo cho tôi không thực sự hữu ích.

Tôi lấy nguồn Hibernate và đặt Nguồn của lớp org.hibernate.mapping.Table vào thư mục nguồn của tôi, đây là khởi đầu của classpath (kết quả jar trong dự án của tôi bắt đầu bằng một chữ cái thấp hơn hibernate.jar, vì vậy điều này thậm chí hoạt động trong các ứng dụng web).

I thay thế chức năng uniqueColumnString với đoạn mã sau (mã gốc ở đầu của hàm):

public String uniqueColumnString(Iterator iterator, String referencedEntityName) { 
//  int result = 0; 
//  if (referencedEntityName != null) { 
//   result += referencedEntityName.hashCode(); 
//  } 
//  while (iterator.hasNext()) { 
//   result += iterator.next().hashCode(); 
//  } 
//  return (Integer.toHexString(name.hashCode()) + Integer.toHexString(result)).toUpperCase(); 
      StringBuilder retVal = new StringBuilder(); 
      retVal.append("_").append(referencedEntityName); 
      while(iterator.hasNext()) { 
       Column c = (Column)iterator.next(); 
       retVal.append("_"); 
       retVal.append(c.getName()); 
      } 
      return retVal.toString(); 
    } 

này trả về chuỗi tự động đẹp như "_Entity_attributeName_id", mà sẽ được sử dụng để tạo ra các phím nước ngoài như "fk_Entity_attributeName_id"! Không bao giờ phải chỉ định lại tên của tôi bằng tay :)))

+0

Đây là một ý tưởng tuyệt vời và tôi sẽ thử nó. –

+0

Vui lòng cho tôi biết cách hoạt động! Tôi chưa bao giờ thử điều này trên một ElementCollection! Và IMHO giải pháp của tôi thậm chí còn tốt hơn mà ngủ đông về tính độc đáo. Giải pháp của họ có thể tạo ra các giá trị trùng lặp, trong khi mỏ của tôi luôn là duy nhất (ít nhất là nó vẫn nằm dưới giới hạn độ dài định danh của Phương ngữ). – Daniel

+0

Bất kỳ lý do nào không phải là câu trả lời được chấp nhận? – Stewart

Các vấn đề liên quan