2021-07-28

Archived: How to map a @ManyToOne association using a non-Primary Key column with JPA and Hibernate

 
https://vladmihalcea.com/how-to-map-a-manytoone-association-using-a-non-primary-key-column/

How to map a @ManyToOne association using a non-Primary Key column with JPA and Hibernate


Last modified: Jan 22, 2019


Imagine having a tool that can automatically detect JPA and Hibernate performance issues. Hypersistence Optimizer is that tool!

Introduction

While answering questions on the Hibernate forum, I stumbled on the following question about using the @ManyToOne annotation when the Foreign Key column on the client side references a non-Primary Key column on the parent side.

In this article, you are going to see how to use the @JoinColumn annotation in order to accommodate non-Primary Key many-to-one associations.

Domain Model

Assuming we have the following tables in our database:

Book and publication tables

The isbn column on the publication and book tables are linked via a Foreign Key constraint which is the base of our @ManyToOne assocation:

Book and Publication entities

Non Primary-Key @ManyToOne mapping

The Book represents the parent side of the association, and it’s mapped as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Entity(name = "Book")
@Table(name = "book")
public class Book
    implements Serializable {
 
    @Id
    @GeneratedValue
    private Long id;
 
    private String title;
 
    private String author;
 
    @NaturalId
    private String isbn;
 
    //Getters and setters omitted for brevity
}

The isbn column is mapped as a @NaturalId since it can be used as a business key as well.

For more details about the @NaturalId annotation, check out this article.

The Publication represents the child of the association, so it’s going to be mapped like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Entity(name = "Publication")
@Table(name = "publication")
public class Publication {
 
    @Id
    @GeneratedValue
    private Long id;
 
    private String publisher;
 
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(
        name = "isbn",
        referencedColumnName = "isbn"
    )
    private Book book;
 
    @Column(
        name = "price_in_cents",
        nullable = false
    )
    private Integer priceCents;
 
    private String currency;
 
    //Getters and setters omitted for brevity
}

By default, the @ManyToOne association assumes that the parent-side entity identifier is to be used to join with the client-side entity Foreign Key column.

However, when using a non-Primary Key association, the referencedColumnName should be used to instruct Hibernate which column should be used on the parent side to establish the many-to-one database relationship.

Testing time

Assuming we have the following entities in our database:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Book book = new Book();
book.setTitle( "High-Performance Java Persistence" );
book.setAuthor( "Vlad Mihalcea" );
book.setIsbn( "978-9730228236" );
entityManager.persist(book);
 
Publication amazonUs = new Publication();
amazonUs.setPublisher( "amazon.com" );
amazonUs.setBook( book );
amazonUs.setPriceCents( 4599 );
amazonUs.setCurrency( "$" );
entityManager.persist( amazonUs );
 
Publication amazonUk = new Publication();
amazonUk.setPublisher( "amazon.co.uk" );
amazonUk.setBook( book );
amazonUk.setPriceCents( 3545 );
amazonUk.setCurrency( "&" );
entityManager.persist( amazonUk );

Upon fetching the Publication along with its associated Book, we can see that the @ManyToOne association works as expected:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Publication publication = entityManager.createQuery(
    "select p " +
    "from Publication p " +
    "join fetch p.book b " +
    "where " +
    "   b.isbn = :isbn and " +
    "   p.currency = :currency", Publication.class)
.setParameter( "isbn""978-9730228236" )
.setParameter( "currency""&" )
.getSingleResult();
 
assertEquals(
    "amazon.co.uk",
    publication.getPublisher()
);
 
assertEquals(
    "High-Performance Java Persistence",
    publication.getBook().getTitle()
);

When executing the JPQL query above, Hibernate generates the following SQL statement:

1
2
3
4
5
6
7
8
9
10
11
12
SELECT
        p.id AS id1_1_0_, b.id AS id1_0_1_,
        p.isbn AS isbn5_1_0_, p.currency AS currency2_1_0_,
        p.price_in_cents AS price_in3_1_0_,
        p.publisher AS publishe4_1_0_,
        b.author AS author2_0_1_, b.isbn AS isbn3_0_1_,
        b.title AS title4_0_1_
FROM    publication p
INNER JOIN
        book b ON p.isbn = b.isbn
WHERE   b.isbn = '978-9730228236'
        AND p.currency = '&'

As you can see, the referencedColumnName allows you to customize the JOIN ON clause so that the isbn column is used instead of the default entity identifier.




































Archived: JPA JoinColumn vs mappedBy

 





JPA JoinColumn vs mappedBy



https://stackoverflow.com/a/53984572

I disagree with the accepted answer here by Óscar López. That answer is inaccurate!

It is NOT @JoinColumn which indicates that this entity is the owner of the relationship. Instead, it is the @ManyToOne annotation which does this (in his example).

The relationship annotations such as @ManyToOne@OneToMany and @ManyToMany tell JPA/Hibernate to create a mapping. By default, this is done through a seperate Join Table.


@JoinColumn

The purpose of @JoinColumn is to create a join column if one does not already exist. If it does, then this annotation can be used to name the join column.


MappedBy

The purpose of the MappedBy parameter is to instruct JPA: Do NOT create another join table as the relationship is already being mapped by the opposite entity of this relationship.



Remember: MappedBy is a property of the relationship annotations whose purpose is to generate a mechanism to relate two entities which by default they do by creating a join table. MappedBy halts that process in one direction.

The entity not using MappedBy is said to be the owner of the relationship because the mechanics of the mapping are dictated within its class through the use of one of the three mapping annotations against the foreign key field. This not only specifies the nature of the mapping but also instructs the creation of a join table. Furthermore, the option to suppress the join table also exists by applying @JoinColumn annotation over the foreign key which keeps it inside the table of the owner entity instead.

So in summary: @JoinColumn either creates a new join column or renames an existing one; whilst the MappedBy parameter works collaboratively with the relationship annotations of the other (child) class in order to create a mapping either through a join table or by creating a foreign key column in the associated table of the owner entity.

To illustrate how MapppedBy works, consider the code below. If MappedBy parameter were to be deleted, then Hibernate would actually create TWO join tables! Why? Because there is a symmetry in many-to-many relationships and Hibernate has no rationale for selecting one direction over the other.

We therefore use MappedBy to tell Hibernate, we have chosen the other entity to dictate the mapping of the relationship between the two entities.

@Entity
public class Driver {
    @ManyToMany(mappedBy = "drivers")
    private List<Cars> cars;
}

@Entity
public class Cars {
    @ManyToMany
    private List<Drivers> drivers;
}

Adding @JoinColumn(name = "driverID") in the owner class (see below), will prevent the creation of a join table and instead, create a driverID foreign key column in the Cars table to construct a mapping:

@Entity
public class Driver {
    @ManyToMany(mappedBy = "drivers")
    private List<Cars> cars;
}

@Entity
public class Cars {
    @ManyToMany
    @JoinColumn(name = "driverID")
    private List<Drivers> drivers;
}










2021-07-25

紧急公关让人印象深刻的台词

 

Source URL: https://movie.douban.com/review/13188894/


本剧让人印象深刻的台词

悦妙曦 评论 紧急公关 2021-02-04 10:05:36
这篇剧评可能有剧透

1.一个真正懂得生活疾苦的人,也一定是一个慈悲的人。

2.成年人的世界是有多面性的。

3.复仇这盘菜,放凉了才好吃。

4.对于很多人来说,失去自由远比不上被人侮辱更加痛苦。

5.真相,只有百分之百确凿的时候才有意义。不然它打着真相的幌子有可能成为伤害他人的利器。

6.有时候,我们想不通一件事往往是因为我们太局限在自己过往的经历中了,我们不知道未来会是什么样子的。

7.在这个世界上,挫折往往不能打倒一个人,打倒一个人的往往都是顽固的观念。

8.一个人出现精神分裂的前兆就是相信自己对工作特别重要。

9.一个不愿意放弃别人的人,一定是一个有人情味的人。

10.我的能力,就是尽我所能,让大家看到事情的真相。

11.我对那些凝视过深渊依然不放弃的人充满了尊重。

12.表面平静,不代表伤害得不够深。

13.最伤元气的就是离婚官司,因为你不得不将枪对准曾经最爱的人。

14.推脱自己的最好方法就是从自己身上找原因。

15.婚姻不只是有感情,更重要的是博弈。

16.但光明背后都有阴影,这就是生存的代价。

17.不是每个女人离开男人都会活不了。

18.年轻是女人的资本,这句话是对女人最大的谎言。

19.老天还真是公平,不论你是当好人还是坏人,它都不会让你的日子好过。

20.人生本如痴人说梦,充满了喧哗与骚动,然而这一切并没有任何意义。

21.想要比别人更多的东西,并不是一件羞耻的事。

22.不管未来发生什么,我们都不要乱了阵脚。

23.不是谁都会为了利益低头的。

24.一个不懂得感恩的人,运气是不会长久的。

25.一步妥协,步步妥协。

26.如果你在乎我的话,我不应该是你的弱点,我应该让你变得更加强大。

27.我也是人啊,也有宕机的时候。

28.真正的爱情,是会让人生出不顾一切的勇气的。

29.你对生活还有不甘心的时候,当然害怕死亡。

30.我以为需要赎罪的只会是有罪的人,可真正有罪的却逍遥法外,无辜的人却要受罚。

31.这就是命运,它凌驾在任何法则之上。

32.我相信爱,不管是一个人对另一个人的爱,还是一个人对世界的爱。爱可以抵抗这个世界的残酷,是唯一可以创造美好奇迹的东西。

33.我希望你能一直按照你的原则做事。

34.过好咱们自己的日子,比什么都强。

35.你只有站在我的角度,才能真正理解我。

36.一个女孩子可以不漂亮,可以不懂事,也可以不温柔,但千万不可以自卑。自卑会让你虚荣虚荣就会让你冒险去脱离正轨,而当你脱离正轨的那一刻起,你就已经输了。终有一天你会发现,你所向往的那些生活,不过都是幻影。

37.一个成熟的人应该先去了解对方,然后依然愿意给他他想要的,这才是真正的爱。

38.逃避一件事情的痛苦要远远大于这件事情本身带来的压力。

39.有些事情,并不是明知结果失败的,就是去了去做它的意义的。

40.你们的道歉,并不是为了求得原谅。

41.只有在极端的事情面前,才能看到平时看不到的人性。

42.既然得不到,至少可以不让人讨厌。

43.到了我们这个年纪,又有几个是容易的呢?

44.解决危机的最好办法,就是承认和正视自己的错误。

45.我愿意为我曾经的错误,承担任何后果。

46.你的伪装,永远都欺骗不了一些人。而这些人,才是你真正在意的人。在这个世界上,只有走正路的人才能获得别人真正的尊重。

47.得不到一个人的爱,当然也得不到一个人的恨。

48.在这个世界上,不是只有表面的输和赢,我更看重我内心的感受,这才是真正有意义的东西。

49.有些感情不是那么浅白,让人一下子就能理解的。当事人都不一定明白,更何况我们这些旁观者?

50.对于一个撰稿人而言,越是擅长使用语言,越明白语言是多么的苍白和无力。

51.人们总是这样,总是在防止自己受到伤害,但是对于有些人来说,伤害了别人,那种负罪感才是最折磨人的。

52.最爱的人,未必是命中注定那个陪伴我们一生的人,但是我们爱过的每一个人,都让我们的自身变得完整,也都只有我们面对生活的勇气。

53.人生而平等,原来只是一句愚弄人的谎话。

54.有些人生而甜蜜欢畅,有些人生而无尽夜长。

55.在这个世界上,不是什么人都有能力去主动选择自己的悲剧的。

56.有些人就算是失败了,也比你体面。

57.公关,如果只考虑客户利益,不考虑公众利益,那还有什么意义呢?

58.无论你是记者,抑或是是其他可以影响舆论的人,或者是坐在电脑桌前的网民们,你们发出的每一句话,你们写下的每一篇报道,甚至于你们在电脑桌前敲下的每一行评论,都有可能把当事人推进无尽的深渊。在这个全民都是自媒体的时代里面,我们每个人手里都有一把无形的刀,可以伤害任何一个人。不利用这把刀作恶,应该是我们每一个人的底线。

59.但当你面对被你伤害人的时候,你才真正明白你赢的有多么地空虚。

60.一个知道自己有罪的人,面对心爱的人,是多么的无力。

61.没人可以拯救我们,只有我们自己。赎罪是卸下包袱的唯一方法。

62.以前,我一直以为这个世界欠我的,但到了现在我才明白,它已经把最好的全都给我了。

63.我这个人最不喜欢告别的场面。

64.人的自我完善,都是在与他人的互动中完成的。

65.我从他们身上感受到的温暖和关爱,远远多于我为他们所做的。

66.我不想说有缘再见的话,大部分从我们生活中离开的人都不会再见。我希望他们只是把我当成人生中的过客,走好接下来的路。

(欢迎大家补充,谢谢!)










2021-07-23

org.springframework.orm.jpa.JpaSystemException: identifier of an instance was altered to null


my case was exception throw during selection(findAll()) within a loop.

what i did was trace down the instance within the loop, identify where i changed the ID previously and patch accordingly.









Google Referrals