2012-10-05 29 views
5

Tôi có đối tượng mới. Tôi muốn biết id trước khi lưu nó. Có thể không? Hoặc có một cách khác cho việc này? Tôi đang sử dụng jpa như orm và oracle làm cơ sở dữ liệu.Làm cách nào để biết id thứ trước khi lưu đối tượng trong jpa

@Id 
@Basic(optional = false) 
@Column(name = "ID", nullable = false) 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "woTypeSeq") 
private Long id; 

Tôi có trường mã trong thực thể của mình. Nếu người dùng không nhập giá trị cho trường code, tôi muốn đặt mã làm id của tổ chức. Nếu tôi vẫn tồn tại thực thể, tất nhiên tôi có thể nhận được id và đặt giá trị mã là id, nhưng đây là cơ sở dữ liệu truy vấn phụ.

tôi muốn làm một cái gì đó như thế

if(entity.getCode()==null) { 
    entity.setCode(entity.getId); 
    jpaDao.saveOrUpdate(entity); 
} 
+1

Bạn có thể tránh được @GeneratedValue, sử dụng máy phát điện cho mình để có được những giá trị và đặt nó là thực thể "bằng tay" – SJuan76

+0

Tôi không muốn đặt nó vào thực thể manual.if tôi nhận được giá trị tiếp theo cho id từ oracle và tôi đặt nó vào id của thực thể mới, là nó hợp lý? – mstzn

Trả lời

5

Sau khi dài nghiên cứu về điều này, cuối cùng tôi đã tìm thấy một giải pháp.

Trong thực tế, nếu bạn sử dụng máy phát điện chuỗi tại JPA, chắc chắn bạn không thể có được id tổ chức trước khi lưu nó trong cơ sở dữ liệu, vì id tiếp theo sẽ được sự phân công của chuỗi cơ sở dữ liệu.

Có một cách để có được những id nếu bạn sử dụng một máy phát điện tùy chỉnh , bạn có thể lấy id trước khi lưu.Dưới đây là thực hiện đơn giản:

public class CustomGenerator extends IdentityGenerator implements Configurable { 

    private IdentifierGenerator defaultGenerator; 

    public Serializable generate(SessionImplementor session, Object object) throws HibernateException { 
     Long idValue = (Long)defaultGenerator.generate(session, object); 
     //idValue will be assigned your entity id 
     return idValue; 
    } 

    @Override 
    public void configure(Type type, Properties params, Dialect d) throws MappingException { 
     DefaultIdentifierGeneratorFactory dd = new DefaultIdentifierGeneratorFactory(); 
     dd.setDialect(d); 
     defaultGenerator = dd.createIdentifierGenerator("sequence", type, params); 
    } 
} 

Sử dụng CustomGenerator cho trường id:

@Id 
@Basic(optional = false) 
@Column(name = "ID", nullable = false) 
@GenericGenerator(name = "seq_id", strategy = "com.yoncabt.abys.core.listener.CustomGenerator", parameters = { @Parameter(name = "sequence", value = "II_FIRM_DOC_PRM_SEQ") }) 
@GeneratedValue(generator = "seq_id") 
private Long id; 
8

Với một loại @GeneratedValue id bạn không thể biết rằng giá trị trước (trước khi thực sự viết nó). Tuy nhiên một khi bạn vẫn còn Bean của bạn, trường id sẽ được cư trú trong trường hợp bean đó và bạn có thể lấy nó mà không cần phải làm một truy vấn bổ sung cho nó. Nói cách khác:

MyEntiry myEnt = new MyEntity(); //the id field is null now 
entityManager.persist(myEnt);//the id field is populated in myEnt now 
Long id = myEnt.getId(); 

Ngoài ra, tùy thuộc vào cách EntityManager bạn được cấu hình, bạn có thể cần phải cũng cam kết đầu tiên giao dịch (bằng tay) trước khi bạn có thể nhận được id đó.

Cập nhật theo bình luận

Nếu bạn muốn chặn và làm điều gì đó để các thực thể trước khi nó được lưu lại và/hoặc cập nhật, bạn có thể sử dụng JPA Listeners Vòng đời (nếu bạn đang sử dụng JPA phiên bản 2): Handling JPA lifecycle event using listeners and callbacks .

Về cơ bản, bạn có thể tạo ra một phương pháp validate() trong đậu của bạn, chú thích nó với @PrePersist@PreUpdate và thực hiện xác nhận trong nó (nếu đang trống bộ nó với giá trị id của)

Cập nhật mỗi comment 2

Có, tôi thành thật chỉ nghĩ về điều đó ngay bây giờ: nếu id được tạo tự động, nó có thể được điền sau khi sự kiện đã tồn tại trước đó, chẳng hạn như khi mã tiền tồn tại của bạn được thực thi bạn vẫn không biết id là gì (bạn cũng có thể thấy rằng trong ví dụ bạn liên kết tới id là NOT autogenerated nhưng được đặt thủ công). Những gì bạn có thể làm trong trường hợp này là thêm trường boolean vào thực thể của bạn (chú thích với @Transient để nó không bị kéo dài) được gọi là isCodeEmpty (mặc định là sai nếu không được khởi tạo cụ thể). Sau đó, trong phương thức chú thích @PrePersist của bạn, bạn kiểm tra xem giá trị của trường mã có trống không và nếu có, hãy đặt giá trị boolean thành true. Sau đó, bạn Refactor phương pháp setId(...) bạn như vậy mà (ngoài đặt trường id) nó sẽ kiểm tra boolean này, và nếu thiết lập đúng giá trị của trường mã như của các trường id:

public class YourEntity { 

@Transient 
private boolean isCodeEmpty; 

public void setId(Whatever id) { 
this.id = id; 
if(isCodeEmpty) { 
    this.code = id; 
    //if necessary: 
    //this.isCodeEmpty = false; 
} 
} 

@PrePersist 
public void validate() { 
if(code == null || code.isEmpty()) { 
    isCodeEmpty = true; 
} 

} 


} 
+0

Cảm ơn bạn đã trả lời. Tôi đã cập nhật câu hỏi của tôi. Bạn có thể kiểm tra nó không? – mstzn

+0

Tôi đã thử thực thể listener.but trong giá trị id người đăng ký là null.I không biết tại sao nó là null.I thực hiện như thế = http://www.java2s.com/Tutorial/Java/0355__JPA/EntityListenersPrePersist.htm bạn có gợi ý hay ý tưởng? Cảm ơn bạn rất nhiều – mstzn

+1

ý tưởng của bạn là tuyệt vời nhưng sau khi prePersist setId() phương pháp không làm việc.Tôi đã làm những gì bạn nói. Tôi gỡ lỗi nó, nhưng phương thức setId không được thực thi và trường mã không set.Prepersist đang làm việc. – mstzn

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