0

我定义了两个实体如下 1.Booking

@Entity
@Table(name="booking")
public class Booking extends BaseModel{
    ..
    @OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
    @JoinColumn(name="bookingNo")
    private List<Part>parts = new ArrayList<Part>();
  ...

2.部分

@Entity
@Table(name="part")
public class Part extends BaseModel{
    @Id
    @GeneratedValue
    private Integer sequence;
    @Column(length=50)
    private String bookingNo;

现在我的问题是首先我保存了一个包含两个部分的预订,然后在视图(JSP)中,我更新了这个预订并添加了一个新部分,最后我将使用第二次创建的新部分再次保存这个预订。如果一切顺利没关系,我认为在 DB 中,它应该有三个部分,是的,它在 DB 中确实有三个部分,第一次保存了两个,第二次保存了第三部分。但让我惊讶的是前两部分外键“bookingNo”更新为空。我正在使用hibernate的saveOrUpdate API。这是因为当我第二次保存预订时,该预订下只有一个部分,这样hibernate会默认删除其他部分(第一次保存的两个部分)?请看我的日志,它有以下日志: 更新部分设置 bookingNo=null where bookingNo=? 保存预订时

21:41:02,476 DEBUG BookingDAO:65 - save(),get session and start save booking
21:41:02,478 DEBUG VersionValue:44 - version unsaved-value strategy UNDEFINED
21:41:02,479 DEBUG IdentifierValue:77 - id unsaved-value strategy UNDEFINED
21:41:02,480 DEBUG AbstractEntityPersister:1004 - Getting current persistent state for: [com.chailie.booking.model.booking.Booking#SAMSUNG-100002]
21:41:02,482 DEBUG AbstractBatcher:358 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
21:41:02,483 DEBUG SQL:393 - select booking_.bookingNo, booking_.bookedBy as bookedBy0_, booking_.bookingDate as bookingD3_0_, booking_.businessService as business4_0_, booking_.cargoType as cargoType0_, booking_.consignee as consignee0_, booking_.consigneeAddress as consigne7_0_, booking_.consigneeCity as consigne8_0_, booking_.consigneeCountry as consigne9_0_, booking_.consigneeName as consign10_0_, booking_.consigneePostal as consign11_0_, booking_.consigneeState as consign12_0_, booking_.createDate as createDate0_, booking_.customer as customer0_, booking_.customerAddress as custome15_0_, booking_.customerCity as custome16_0_, booking_.customerCountry as custome17_0_, booking_.customerName as custome18_0_, booking_.customerPostal as custome19_0_, booking_.customerState as custome20_0_, booking_.frtPayTerm as frtPayTerm0_, booking_.incoterms as incoterms0_, booking_.otherPayTerm as otherPa23_0_, booking_.remark as remark0_, booking_.serviceLevel as service25_0_, booking_.shipper as shipper0_, booking_.shipperAddress as shipper27_0_, booking_.shipperCity as shipper28_0_, booking_.shipperCountry as shipper29_0_, booking_.shipperName as shipper30_0_, booking_.shipperPostal as shipper31_0_, booking_.shipperState as shipper32_0_, booking_.status as status0_, booking_.timestamp as timestamp0_ from booking booking_ where booking_.bookingNo=?
21:41:02,487 DEBUG AbstractBatcher:476 - preparing statement
21:41:02,489 DEBUG StringType:80 - binding 'SAMSUNG-100002' to parameter: 1
21:41:02,492 DEBUG StringType:122 - returning 'chailieyang' as column: bookedBy0_
21:41:02,494 DEBUG TimestampType:122 - returning '2013-06-06 00:00:00' as column: bookingD3_0_
21:41:02,496 DEBUG StringType:122 - returning 'sea' as column: business4_0_
21:41:02,497 DEBUG StringType:122 - returning '' as column: cargoType0_
21:41:02,498 DEBUG StringType:122 - returning 'LENOVO' as column: consignee0_
21:41:02,500 DEBUG StringType:122 - returning '' as column: consigne7_0_
21:41:02,501 DEBUG StringType:122 - returning '' as column: consigne8_0_
21:41:02,502 DEBUG StringType:122 - returning 'USA' as column: consigne9_0_
21:41:02,503 DEBUG StringType:122 - returning 'Zhao Yang,Bei JIng China' as column: consign10_0_
21:41:02,504 DEBUG StringType:122 - returning '' as column: consign11_0_
21:41:02,505 DEBUG StringType:122 - returning 'ALABAMA' as column: consign12_0_
21:41:02,506 DEBUG TimestampType:122 - returning '2013-05-02 21:39:03' as column: createDate0_
21:41:02,507 DEBUG StringType:122 - returning 'SAMSUNG' as column: customer0_
21:41:02,508 DEBUG StringType:122 - returning '' as column: custome15_0_
21:41:02,509 DEBUG StringType:122 - returning '' as column: custome16_0_
21:41:02,510 DEBUG StringType:122 - returning 'USA' as column: custome17_0_
21:41:02,511 DEBUG StringType:122 - returning 'Samsung CO,Korea' as column: custome18_0_
21:41:02,512 DEBUG StringType:122 - returning '' as column: custome19_0_
21:41:02,514 DEBUG StringType:122 - returning 'ALABAMA' as column: custome20_0_
21:41:02,514 DEBUG StringType:122 - returning '' as column: frtPayTerm0_
21:41:02,515 DEBUG StringType:122 - returning '' as column: incoterms0_
21:41:02,516 DEBUG StringType:122 - returning '' as column: otherPa23_0_
21:41:02,517 DEBUG StringType:122 - returning '' as column: remark0_
21:41:02,518 DEBUG StringType:122 - returning '' as column: service25_0_
21:41:02,519 DEBUG StringType:122 - returning 'SAMSUNG' as column: shipper0_
21:41:02,520 DEBUG StringType:122 - returning '' as column: shipper27_0_
21:41:02,521 DEBUG StringType:122 - returning '' as column: shipper28_0_
21:41:02,522 DEBUG StringType:122 - returning 'USA' as column: shipper29_0_
21:41:02,524 DEBUG StringType:122 - returning 'Samsung CO,Korea' as column: shipper30_0_
21:41:02,527 DEBUG StringType:122 - returning '' as column: shipper31_0_
21:41:02,528 DEBUG StringType:122 - returning 'ALABAMA' as column: shipper32_0_
21:41:02,531 DEBUG StringType:122 - returning 'N' as column: status0_
21:41:02,532 DEBUG TimestampType:122 - returning '2013-05-02 21:39:49' as column: timestamp0_
21:41:02,533 DEBUG AbstractBatcher:366 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
21:41:02,534 DEBUG AbstractBatcher:525 - closing statement
21:41:02,535 DEBUG AbstractSaveEventListener:498 - detached instance of: com.chailie.booking.model.booking.Booking
21:41:02,536 DEBUG DefaultSaveOrUpdateEventListener:203 - updating detached instance
21:41:02,537 DEBUG DefaultSaveOrUpdateEventListener:249 - updating [com.chailie.booking.model.booking.Booking#SAMSUNG-100002]
21:41:02,538 DEBUG ReattachVisitor:60 - collection dereferenced while transient [com.chailie.booking.model.booking.Booking.parts#SAMSUNG-100002]
21:41:02,539 DEBUG ReattachVisitor:60 - collection dereferenced while transient [com.chailie.booking.model.booking.Booking.toDoItems#SAMSUNG-100002]
21:41:02,540 DEBUG DefaultSaveOrUpdateEventListener:298 - updating [com.chailie.booking.model.booking.Booking#SAMSUNG-100002]
21:41:02,541 DEBUG Cascade:115 - processing cascade ACTION_SAVE_UPDATE for: com.chailie.booking.model.booking.Booking
21:41:02,542 DEBUG Cascade:291 - cascade ACTION_SAVE_UPDATE for collection: com.chailie.booking.model.booking.Booking.parts
21:41:02,543 DEBUG CascadingAction:216 - cascading to saveOrUpdate: com.chailie.booking.model.booking.Part
21:41:02,545 DEBUG AbstractSaveEventListener:489 - transient instance of: com.chailie.booking.model.booking.Part
21:41:02,546 DEBUG DefaultSaveOrUpdateEventListener:161 - saving transient instance
21:41:02,547 DEBUG AbstractSaveEventListener:152 - saving [com.chailie.booking.model.booking.Part#<null>]
21:41:02,548 DEBUG AbstractSaveEventListener:240 - executing insertions
21:41:02,550 DEBUG Versioning:42 - Seeding: 2013-05-02 21:41:02.549
21:41:02,552 DEBUG AbstractSaveEventListener:289 - executing identity-insert immediately
21:41:02,555 DEBUG AbstractEntityPersister:2094 - Inserting entity: com.chailie.booking.model.booking.Part (native id)
21:41:02,557 DEBUG AbstractEntityPersister:2096 - Version: 2013-05-02 21:41:02.549
21:41:02,559 DEBUG AbstractBatcher:358 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
21:41:02,563 DEBUG SQL:393 - insert into part (bookingNo, createDate, partNo, poNo, qtyReceived, qtyShipped, qtyUnit, timestamp) values (?, ?, ?, ?, ?, ?, ?, ?)
21:41:02,566 DEBUG AbstractBatcher:476 - preparing statement
21:41:02,570 DEBUG AbstractEntityPersister:1942 - Dehydrating entity: [com.chailie.booking.model.booking.Part#<null>]
21:41:02,572 DEBUG StringType:80 - binding 'SAMSUNG-100002' to parameter: 1
21:41:02,574 DEBUG TimestampType:73 - binding null to parameter: 2
21:41:02,577 DEBUG StringType:80 - binding '' to parameter: 3
21:41:02,579 DEBUG StringType:80 - binding '9999' to parameter: 4
21:41:02,587 DEBUG IntegerType:73 - binding null to parameter: 5
21:41:02,590 DEBUG IntegerType:73 - binding null to parameter: 6
21:41:02,591 DEBUG StringType:80 - binding '' to parameter: 7
21:41:02,595 DEBUG TimestampType:80 - binding '2013-05-02 21:41:02' to parameter: 8
21:41:02,598 DEBUG IdentifierGeneratorFactory:37 - Natively generated identity: 4
21:41:02,600 DEBUG AbstractBatcher:366 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
21:41:02,602 DEBUG AbstractBatcher:525 - closing statement
21:41:02,605 DEBUG Cascade:306 - done cascade ACTION_SAVE_UPDATE for collection: com.chailie.booking.model.booking.Booking.parts
21:41:02,606 DEBUG Cascade:150 - done processing cascade ACTION_SAVE_UPDATE for: com.chailie.booking.model.booking.Booking
21:41:02,608 DEBUG BookingDAO:68 - After save booking,the booking is [com.chailie.booking.model.booking.Booking@5774a1e3]
21:41:02,611 DEBUG JDBCTransaction:103 - commit
21:41:02,612 DEBUG SessionImpl:337 - automatically flushing session
21:41:02,614 DEBUG AbstractFlushingEventListener:58 - flushing session
21:41:02,615 DEBUG AbstractFlushingEventListener:111 - processing flush-time cascades
21:41:02,616 DEBUG Cascade:115 - processing cascade ACTION_SAVE_UPDATE for: com.chailie.booking.model.booking.Booking
21:41:02,618 DEBUG Cascade:291 - cascade ACTION_SAVE_UPDATE for collection: com.chailie.booking.model.booking.Booking.parts
21:41:02,619 DEBUG CascadingAction:216 - cascading to saveOrUpdate: com.chailie.booking.model.booking.Part
21:41:02,620 DEBUG AbstractSaveEventListener:463 - persistent instance of: com.chailie.booking.model.booking.Part
21:41:02,621 DEBUG DefaultSaveOrUpdateEventListener:105 - ignoring persistent instance
21:41:02,623 DEBUG DefaultSaveOrUpdateEventListener:142 - object already associated with session: [com.chailie.booking.model.booking.Part#4]
21:41:02,625 DEBUG Cascade:306 - done cascade ACTION_SAVE_UPDATE for collection: com.chailie.booking.model.booking.Booking.parts
21:41:02,626 DEBUG Cascade:150 - done processing cascade ACTION_SAVE_UPDATE for: com.chailie.booking.model.booking.Booking
21:41:02,627 DEBUG AbstractFlushingEventListener:154 - dirty checking collections
21:41:02,628 DEBUG AbstractFlushingEventListener:171 - Flushing entities and processing referenced collections
21:41:02,630 DEBUG WrapVisitor:87 - Wrapped collection in role: com.chailie.booking.model.booking.Booking.parts
21:41:02,631 DEBUG Collections:176 - Collection found: [com.chailie.booking.model.booking.Booking.parts#SAMSUNG-100002], was: [<unreferenced>] (initialized)
21:41:02,633 DEBUG AbstractFlushingEventListener:210 - Processing unreferenced collections
21:41:02,635 DEBUG AbstractFlushingEventListener:224 - Scheduling collection removes/(re)creates/updates
21:41:02,636 DEBUG AbstractFlushingEventListener:85 - Flushed: 0 insertions, 0 updates, 0 deletions to 2 objects
21:41:02,637 DEBUG AbstractFlushingEventListener:91 - Flushed: 1 (re)creations, 0 updates, 2 removals to 1 collections
21:41:02,638 DEBUG Printer:83 - listing entities:
21:41:02,639 DEBUG Printer:90 - com.chailie.booking.model.booking.Part{timestamp=2013-05-02 21:41:02, poNo=9999, qtyShipped=null, partNo=, sequence=4, bookingNo=SAMSUNG-100002, qtyReceived=null, createDate=null, qtyUnit=}
21:41:02,641 DEBUG Printer:90 - com.chailie.booking.model.booking.Booking{remark=, consignee=LENOVO, customerCity=, customerState=ALABAMA, parts=[com.chailie.booking.model.booking.Part#4], serviceLevel=, customer=SAMSUNG, otherPayTerm=, consigneeCity=, consigneePostal=, timestamp=2013-05-02 21:39:49, businessService=sea, shipperName=Samsung CO,Korea, customerCountry=USA, cargoType=, shipperCity=, createDate=2013-05-02 21:39:03, customerPostal=, shipperPostal=, customerName=Samsung CO,Korea, consigneeName=Zhao Yang,Bei JIng China, bookingDate=2013-06-06 00:00:00, consigneeAddress=, incoterms=, status=N, shipperCountry=USA, shipper=SAMSUNG, bookingNo=SAMSUNG-100002, shipperState=ALABAMA, shipperAddress=, toDoItems=null, consigneeCountry=USA, customerAddress=, frtPayTerm=, consigneeState=ALABAMA, bookedBy=chailieyang}
21:41:02,644 DEBUG AbstractFlushingEventListener:290 - executing flush
21:41:02,646 DEBUG ConnectionManager:463 - registering flush begin
21:41:02,647 DEBUG AbstractCollectionPersister:1010 - Deleting collection: [com.chailie.booking.model.booking.Booking.parts#SAMSUNG-100002]
21:41:02,648 DEBUG AbstractBatcher:358 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
21:41:02,650 DEBUG SQL:393 - update part set bookingNo=null where bookingNo=?
21:41:02,651 DEBUG AbstractBatcher:476 - preparing statement
21:41:02,653 DEBUG StringType:80 - binding 'SAMSUNG-100002' to parameter: 1
21:41:02,655 DEBUG AbstractCollectionPersister:1067 - done deleting collection
21:41:02,656 DEBUG AbstractCollectionPersister:1010 - Deleting collection: [com.chailie.booking.model.booking.Booking.toDoItems#SAMSUNG-100002]
21:41:02,657 DEBUG AbstractBatcher:44 - Executing batch size: 1
21:41:02,660 DEBUG AbstractBatcher:366 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
21:41:02,661 DEBUG AbstractBatcher:525 - closing statement
21:41:02,663 DEBUG AbstractBatcher:358 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
21:41:02,664 DEBUG SQL:393 - update todoitem set bookingNo=null where bookingNo=?
21:41:02,666 DEBUG AbstractBatcher:476 - preparing statement
21:41:02,668 DEBUG StringType:80 - binding 'SAMSUNG-100002' to parameter: 1
21:41:02,669 DEBUG AbstractCollectionPersister:1067 - done deleting collection
21:41:02,670 DEBUG AbstractBatcher:44 - Executing batch size: 1
21:41:02,672 DEBUG AbstractBatcher:366 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
21:41:02,673 DEBUG AbstractBatcher:525 - closing statement
21:41:02,675 DEBUG AbstractCollectionPersister:1090 - Inserting collection: [com.chailie.booking.model.booking.Booking.parts#SAMSUNG-100002]
21:41:02,677 DEBUG AbstractBatcher:358 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
21:41:02,679 DEBUG SQL:393 - update part set bookingNo=? where sequence=?
21:41:02,682 DEBUG AbstractBatcher:476 - preparing statement
21:41:02,685 DEBUG StringType:80 - binding 'SAMSUNG-100002' to parameter: 1
21:41:02,687 DEBUG IntegerType:80 - binding '4' to parameter: 2
21:41:02,688 DEBUG AbstractCollectionPersister:1172 - done inserting collection: 1 rows inserted
21:41:02,689 DEBUG AbstractBatcher:44 - Executing batch size: 1
21:41:02,692 DEBUG AbstractBatcher:366 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
21:41:02,694 DEBUG AbstractBatcher:525 - closing statement
21:41:02,695 DEBUG ConnectionManager:472 - registering flush end
21:41:02,696 DEBUG AbstractFlushingEventListener:321 - post flush
21:41:02,697 DEBUG JDBCContext:201 - before transaction completion
21:41:02,698 DEBUG SessionImpl:393 - before transaction completion
21:41:02,889 DEBUG JDBCTransaction:193 - re-enabling autocommit
21:41:02,891 DEBUG JDBCTransaction:116 - committed JDBC Connection
21:41:02,893 DEBUG JDBCContext:215 - after transaction completion
21:41:02,895 DEBUG ConnectionManager:296 - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
21:41:02,896 DEBUG SessionImpl:422 - after transaction completion
21:41:02,897 DEBUG SessionImpl:353 - automatically closing session
21:41:02,898 DEBUG SessionImpl:273 - closing session
21:41:02,899 DEBUG ConnectionManager:374 - performing cleanup
21:41:02,900 DEBUG ConnectionManager:435 - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
21:41:02,901 DEBUG JDBCContext:215 - after transaction completion
21:41:02,902 DEBUG ConnectionManager:296 - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
21:41:02,904 DEBUG SessionImpl:422 - after transaction completion
21:41:02,905 DEBUG SessionImpl:273 - closing session
21:41:02,906 DEBUG BookingUtil:298 - initBooking() start with booking [com.chailie.booking.model.booking.Booking@5774a1e3],user [User [userName=chailieyang, loginIp=0:0:0:0:0:0:0:1]]
21:41:02,907 DEBUG BookingUtil:111 - initToDoItems start with todoitems [null]
21:41:02,918 DEBUG BookingUtil:75 - initToDoItems() start,init complete todoitem
21:41:02,922 DEBUG ServletDispatcherResult:68 - Forwarding to location newbooking.jsp
4

3 回答 3

0

我认为我的问题是由于我之前将零件的 FK 设置为可为空的,在我指定 FK 不可为空后,它将不再有该问题,请参阅我的零件实体

@Entity
@Table(name="part")
public class Part extends BaseModel{
    @Id
    @GeneratedValue
    private Integer sequence;
    @Column(length=50,nullable=false,insertable=false,updatable=false)
于 2013-05-04T03:49:05.703 回答
0

只是想为其他人添加我遇到相同问题的解决方案,最终解决方案是inverse="true"我的收藏元素缺乏。

这里的好文章解释了为什么逆真对于集合来说是个好主意。

于 2016-06-09T17:20:09.150 回答
-1

您不能混合使用 @OneToMany 和 @JoinColumn 注释。

“booking”表不能引用“part”表,因为没有可扩展的方式来存储许多部分 id:“booking”表是否需要有“partId”列?如果预订可以有很多部分,是否需要在该列中用逗号分隔部分 ID?

相反,关系的拥有方需要位于“多”方,在本例中为“部分”表:

@Entity
@Table(name="booking")
public class Booking extends BaseModel{
    ..
    @OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY, mappedBy="booking")
    private List<Part>parts = new ArrayList<Part>();
    ..
}

@Entity
@Table(name="part")
public class Part extends BaseModel{
    @Id
    @GeneratedValue
    private Integer sequence;

    @ManyToOne
    @JoinColumn(length=50, name="bookingNo")
    private Booking booking;
    ..
}

请注意在 Part 实体中使用 @ManyToOne 注释来指示它是关系的拥有方。Booking实体中的@OneToMany注解需要参数“mappedBy”,表示“Part”实体中用@ManyToOne注解的字段,同时也表示Booking实体是关系的反面。

编辑:

正如erencan 所指出的,实际上您可以混合使用@OneToMany 和@JoinColumn,表格将以与使用@ManyToOne 相同的结构结尾。Part 实体中的成员变量“bookingNo”似乎很奇怪,因为它不需要进行映射。如果需要,@ManyToOne 可用于获取有关 Booking 实体的信息。

于 2013-05-02T15:43:28.523 回答