SlideShare a Scribd company logo
www.luxoft.com
How to Use Hibernate:
Key Problems and Solutions
Andriy Slobodyanyk
www.luxoft.com
@Column(
name = "first_name",
length = 32,
nullable = false
)
private String firstName;
● Для чего нужен атрибут nullable?
● Можно ли создать и сохранить entity, если в поле name будет значение null?
● Проверяется ли длина поля?
● В чем отличие этих атрибутов @Column и
аннотаций @javax.validation.constraints.NotNull и @Size?
2
www.luxoft.com 3
https://dou.ua/lenta/articles/how-to-use-hibernate/
www.luxoft.com 4
Техническое задание
www.luxoft.com
• дата создания
• статус — новый, в обработке и т. д.
• срочность
• адрес доставки
• товары / количество
• цена с валютой товара
• клиент
5
Заказ
www.luxoft.com 6
www.luxoft.com 7
@Entity
@Table(name = "orders")
public class OrderEntity {
@Id
private Long id;
private LocalDateTime created;
private String status; // see StatusConstants
private Integer express;
private String addressCity;
private String addressStreet;
private String addressBuilding;
private Long clientId;
}
@Entity
@Table(name = "items")
public class Item {
@Id
private Long id;
private String name;
private BigDecimal priceAmount;
private String priceCurrency;
}
www.luxoft.com 8
www.luxoft.com 9
class Order {
LocalDateTime created;
Status status;
boolean express;
Address address;
Map<Item, Integer> items;
Client client;
}
class Address {
String city;
String street;
String building;
}
class Item {
String name;
Money price;
}
class Client {
String firstName;
String lastName;
}
www.luxoft.com 10
private Map<Item, Integer> items = new HashMap<>();
public Map<Item, Integer> getItems() {
return Collections.unmodifiableMap(items);
}
public void addItem(Item item) {
items.merge(item, 1, (v1, v2) -> v1 + v2);
}
public void removeItem(Item item) {
items.computeIfPresent(item, (k, v) -> v > 1 ? v - 1 : null);
}
www.luxoft.com
Подключаем JPA
● @Entity и @Id / @Embeddable
● Примитивы, числа, строки и даты
● @Enumerated и EnumType.ORDINAL / EnumType.STRING
● AttributeConverter
● @Type
● @ManyToOne, @OneToMany, @ElementCollection
● @Table
● @Column
11
www.luxoft.com
@Column -> DDL
12
@Column(
name = "first_name",
nullable = false,
length = 32
)
private String firstName;
create table … (
first_name varchar(32) not null
)
www.luxoft.com
(Не)использование Id
13
boolean equals =
order.getId().equals(anotherOrder.getId());
boolean contains = orders.stream().anyMatch(
o -> .getId().equals(someOrder.getId());
select o from Order o where o.client.id =
:clientId
boolean equals = order.equals(anotherOrder);
boolean contains = orders.contains(someOrder);
select o from Order o where o.client = :client
www.luxoft.com
Эквивалентность (методы equals/hashCode)
14
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Order that = (Order) o;
return Objects.equals(id, that.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Order)) return false;
Order order = (Order) o;
return Objects.equals(created, order.created)
&& Objects.equals(client, order.client);
}
@Override
public int hashCode() {
return Objects.hash(created, client);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Item)) return false;
Item that = (Item) o;
return Objects.equals(id, that.id);
}
@Override
public int hashCode() {
return 31;
}
www.luxoft.com 15
Проблемы
www.luxoft.com
Проблемы
16
• Entity и DTO
• @Transient
• entityManager.detach()
• FetchType.EAGER
• EntityManager.flush() и clear()
• Lombok @Data
www.luxoft.com
MapStruct
17
@Mapper
public interface Mapper {
FooDto toDto(Foo foo);
}
www.luxoft.com 18
@Getter
@EqualsAndHashCode(of = {"firstName", "lastName"})
@ToString(of = {"firstName", "lastName"})
@NoArgsConstructor
@Entity
@Table(name = "clients")
public class Client {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 32, nullable = false)
private String firstName;
@Column(length = 32, nullable = false)
private String lastName;
public Client(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
@Getter
@EqualsAndHashCode(of = "name")
@ToString(of = {"name", "price"})
@NoArgsConstructor
@Entity
@Table(name = "items")
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 32)
private String name;
@Columns(
columns = {
@Column(name = "price_currency", length = 3, nullable = false),
@Column(name = "price_amount", precision = 7, scale = 2, nullable = false)
}
)
@Type(type = "org.jadira.usertype.moneyandcurrency.moneta.PersistentMoneyAmountAndCurrency")
private Money price;
public Item(String name, Money price) {
this.name = name;
this.price = price;
}
}
www.luxoft.com
1
@Getter
@EqualsAndHashCode(of = {"city", "street", "building"})
@ToString(of = {"city", "street", "building"})
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class Address {
private String city;
private String street;
private String building;
}
@AllArgsConstructor
public enum Status {
NEW("N"),
PROCESSING("P"),
COMPLETED("C"),
DEFERRED("D");
@Getter
private final String code;
}
@Converter(autoApply = true)
public class StatusConverter implements
AttributeConverter<Status, String> {
@Override
public String convertToDatabaseColumn(Status status) {
return status.getCode();
}
@Override
public Status convertToEntityAttribute(String code) {
for (Status status : Status.values()) {
if (status.getCode().equals(code)) {
return status;
}
}
throw new IllegalArgumentException(
"Unknown code " + code
);
}
}
www.luxoft.com
2
@Getter
@EqualsAndHashCode(of = {"created", "client"})
@ToString(of = {"created", "address", "express", "status"})
@NoArgsConstructor
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private LocalDateTime created = LocalDateTime.now();
@AttributeOverrides({
@AttributeOverride(name = "city", column = @Column(name = "address_city", nullable = false, length = 32)),
@AttributeOverride(name = "street", column = @Column(name = "address_street", nullable = false, length = 32)),
@AttributeOverride(name = "building", column = @Column(name = "address_building", nullable = false, length = 32))
})
private Address address;
@Setter
private boolean express;
@Column(length = 1, nullable = false)
@Setter
private Status status = Status.NEW;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST, optional = false)
private Client client;
@ElementCollection
@Column(name = "quantity", nullable = false)
@MapKeyJoinColumn(name = "item_id")
@LazyCollection(LazyCollectionOption.EXTRA)
private Map<Item, Integer> items = new HashMap<>();
}
www.luxoft.com 21
Check List
www.luxoft.com
Check List
22
● entities состоят из большого количества примитивных полей, а не из классов
● вместо enum-ов используются строковые константы
● методы equals/hashCode не определены
● в бизнес-логике и запросах фигурируют id
● происходит смешение Entity и Dto в одном классе
● использование FetchType.EAGER, в том числе по умолчанию в @ManyToOne
● ненужные вызовы flush() и clear()
● неаккуратное использование Lombok
www.luxoft.com
Thank you!

More Related Content

ZIP
Lisp Macros in 20 Minutes (Featuring Clojure)
PDF
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
PDF
Justjava 2007 Arquitetura Java EE Paulo Silveira, Phillip Calçado
PDF
The Ring programming language version 1.5.4 book - Part 82 of 185
PPTX
Javascript Execution Context Flow
PDF
All things that are not code
PDF
Promise: async programming hero
PDF
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...
Lisp Macros in 20 Minutes (Featuring Clojure)
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
Justjava 2007 Arquitetura Java EE Paulo Silveira, Phillip Calçado
The Ring programming language version 1.5.4 book - Part 82 of 185
Javascript Execution Context Flow
All things that are not code
Promise: async programming hero
NodeUkraine - Postgresql для хипстеров или почему ваш следующий проект должен...

What's hot (19)

PDF
jq: JSON - Like a Boss
PDF
Jason parsing
PDF
Introduction to JQ
PPTX
Improving Correctness with Types
PPTX
Introduction to Unit Testing (Part 2 of 2)
PPTX
Improving Correctness With Type - Goto Con Berlin
PDF
Zhongl scala summary
PDF
Anonymous functions in JavaScript
PDF
Building fast interpreters in Rust
PPTX
Why Sifu
PPTX
JavaScript - i och utanför webbläsaren (2010-03-03)
PDF
Declaring friend function with inline code
PDF
[2019-07] GraphQL in depth (serverside)
PDF
Rust ⇋ JavaScript
PDF
Rajeev oops 2nd march
DOC
Marcus Portfolio
PDF
Let the type system be your friend
PDF
Alexey Tsoy Meta Programming in C++ 16.11.17
PDF
Bind me if you can
jq: JSON - Like a Boss
Jason parsing
Introduction to JQ
Improving Correctness with Types
Introduction to Unit Testing (Part 2 of 2)
Improving Correctness With Type - Goto Con Berlin
Zhongl scala summary
Anonymous functions in JavaScript
Building fast interpreters in Rust
Why Sifu
JavaScript - i och utanför webbläsaren (2010-03-03)
Declaring friend function with inline code
[2019-07] GraphQL in depth (serverside)
Rust ⇋ JavaScript
Rajeev oops 2nd march
Marcus Portfolio
Let the type system be your friend
Alexey Tsoy Meta Programming in C++ 16.11.17
Bind me if you can
Ad

Similar to Andriy Slobodyanyk "How to Use Hibernate: Key Problems and Solutions" (10)

PPT
Spring data
ODP
Java Persistence API
PPT
04 Data Access
PPTX
Advanced Hibernate V2
PPTX
Introduction to Hibernate Framework
PPTX
Introduction to Hibernate Framework
PPTX
PPT
Why hibernater1
PPT
Introduction to hibernate
Spring data
Java Persistence API
04 Data Access
Advanced Hibernate V2
Introduction to Hibernate Framework
Introduction to Hibernate Framework
Why hibernater1
Introduction to hibernate
Ad

More from LogeekNightUkraine (20)

PPTX
Face recognition with c++
PPTX
C++20 features
PPTX
Autonomous driving on your developer pc. technologies, approaches, future
PDF
Orkhan Gasimov "High Performance System Design"
PPTX
Vitalii Korzh "Managed Workflows or How to Master Data"
PDF
Yevhen Tatarynov "From POC to High-Performance .NET applications"
PDF
Oleksii Kuchuk "Reading gauge values with open cv imgproc"
PDF
Oleksandr Kutsan "Using katai struct to describe the process of working with ...
PDF
Pavlo Zhdanov "Mastering solid and base principles for software design"
PDF
Serhii Zemlianyi "Error Retries with Exponential Backoff Using RabbitMQ"
PDF
Iurii Antykhovych "Java and performance tools and toys"
PDF
Eugene Bova "Dapr (Distributed Application Runtime) in a Microservices Archit...
PPTX
Aleksandr Kutsan "Managing Dependencies in C++"
PDF
Yevhen Tatarynov "My .NET Application Allocates too Much Memory. What Can I Do?"
PDF
Alexandr Golyak, Nikolay Chertkov "Automotive Testing vs Test Automatio"
PPTX
Michal Kordas "Docker: Good, Bad or Both"
PPTX
Kolomiyets Dmytro "Dealing with Multiple Caches, When Developing Microservices"
PPTX
Shestakov Illia "The Sandbox Theory"
PPTX
Dmytro Kochergin “Autotest with CYPRESS”
PPTX
Ivan Dryzhyruk “Ducks Don’t Like Bugs”
Face recognition with c++
C++20 features
Autonomous driving on your developer pc. technologies, approaches, future
Orkhan Gasimov "High Performance System Design"
Vitalii Korzh "Managed Workflows or How to Master Data"
Yevhen Tatarynov "From POC to High-Performance .NET applications"
Oleksii Kuchuk "Reading gauge values with open cv imgproc"
Oleksandr Kutsan "Using katai struct to describe the process of working with ...
Pavlo Zhdanov "Mastering solid and base principles for software design"
Serhii Zemlianyi "Error Retries with Exponential Backoff Using RabbitMQ"
Iurii Antykhovych "Java and performance tools and toys"
Eugene Bova "Dapr (Distributed Application Runtime) in a Microservices Archit...
Aleksandr Kutsan "Managing Dependencies in C++"
Yevhen Tatarynov "My .NET Application Allocates too Much Memory. What Can I Do?"
Alexandr Golyak, Nikolay Chertkov "Automotive Testing vs Test Automatio"
Michal Kordas "Docker: Good, Bad or Both"
Kolomiyets Dmytro "Dealing with Multiple Caches, When Developing Microservices"
Shestakov Illia "The Sandbox Theory"
Dmytro Kochergin “Autotest with CYPRESS”
Ivan Dryzhyruk “Ducks Don’t Like Bugs”

Recently uploaded (20)

PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPTX
sap open course for s4hana steps from ECC to s4
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Review of recent advances in non-invasive hemoglobin estimation
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Empathic Computing: Creating Shared Understanding
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
Big Data Technologies - Introduction.pptx
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Encapsulation theory and applications.pdf
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PPT
Teaching material agriculture food technology
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
Agricultural_Statistics_at_a_Glance_2022_0.pdf
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
sap open course for s4hana steps from ECC to s4
Understanding_Digital_Forensics_Presentation.pptx
Review of recent advances in non-invasive hemoglobin estimation
MYSQL Presentation for SQL database connectivity
Empathic Computing: Creating Shared Understanding
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Big Data Technologies - Introduction.pptx
The Rise and Fall of 3GPP – Time for a Sabbatical?
Building Integrated photovoltaic BIPV_UPV.pdf
The AUB Centre for AI in Media Proposal.docx
Encapsulation theory and applications.pdf
Chapter 3 Spatial Domain Image Processing.pdf
Teaching material agriculture food technology
Unlocking AI with Model Context Protocol (MCP)
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Advanced methodologies resolving dimensionality complications for autism neur...

Andriy Slobodyanyk "How to Use Hibernate: Key Problems and Solutions"

  • 1. www.luxoft.com How to Use Hibernate: Key Problems and Solutions Andriy Slobodyanyk
  • 2. www.luxoft.com @Column( name = "first_name", length = 32, nullable = false ) private String firstName; ● Для чего нужен атрибут nullable? ● Можно ли создать и сохранить entity, если в поле name будет значение null? ● Проверяется ли длина поля? ● В чем отличие этих атрибутов @Column и аннотаций @javax.validation.constraints.NotNull и @Size? 2
  • 5. www.luxoft.com • дата создания • статус — новый, в обработке и т. д. • срочность • адрес доставки • товары / количество • цена с валютой товара • клиент 5 Заказ
  • 7. www.luxoft.com 7 @Entity @Table(name = "orders") public class OrderEntity { @Id private Long id; private LocalDateTime created; private String status; // see StatusConstants private Integer express; private String addressCity; private String addressStreet; private String addressBuilding; private Long clientId; } @Entity @Table(name = "items") public class Item { @Id private Long id; private String name; private BigDecimal priceAmount; private String priceCurrency; }
  • 9. www.luxoft.com 9 class Order { LocalDateTime created; Status status; boolean express; Address address; Map<Item, Integer> items; Client client; } class Address { String city; String street; String building; } class Item { String name; Money price; } class Client { String firstName; String lastName; }
  • 10. www.luxoft.com 10 private Map<Item, Integer> items = new HashMap<>(); public Map<Item, Integer> getItems() { return Collections.unmodifiableMap(items); } public void addItem(Item item) { items.merge(item, 1, (v1, v2) -> v1 + v2); } public void removeItem(Item item) { items.computeIfPresent(item, (k, v) -> v > 1 ? v - 1 : null); }
  • 11. www.luxoft.com Подключаем JPA ● @Entity и @Id / @Embeddable ● Примитивы, числа, строки и даты ● @Enumerated и EnumType.ORDINAL / EnumType.STRING ● AttributeConverter ● @Type ● @ManyToOne, @OneToMany, @ElementCollection ● @Table ● @Column 11
  • 12. www.luxoft.com @Column -> DDL 12 @Column( name = "first_name", nullable = false, length = 32 ) private String firstName; create table … ( first_name varchar(32) not null )
  • 13. www.luxoft.com (Не)использование Id 13 boolean equals = order.getId().equals(anotherOrder.getId()); boolean contains = orders.stream().anyMatch( o -> .getId().equals(someOrder.getId()); select o from Order o where o.client.id = :clientId boolean equals = order.equals(anotherOrder); boolean contains = orders.contains(someOrder); select o from Order o where o.client = :client
  • 14. www.luxoft.com Эквивалентность (методы equals/hashCode) 14 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Order that = (Order) o; return Objects.equals(id, that.id); } @Override public int hashCode() { return Objects.hash(id); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Order)) return false; Order order = (Order) o; return Objects.equals(created, order.created) && Objects.equals(client, order.client); } @Override public int hashCode() { return Objects.hash(created, client); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Item)) return false; Item that = (Item) o; return Objects.equals(id, that.id); } @Override public int hashCode() { return 31; }
  • 16. www.luxoft.com Проблемы 16 • Entity и DTO • @Transient • entityManager.detach() • FetchType.EAGER • EntityManager.flush() и clear() • Lombok @Data
  • 18. www.luxoft.com 18 @Getter @EqualsAndHashCode(of = {"firstName", "lastName"}) @ToString(of = {"firstName", "lastName"}) @NoArgsConstructor @Entity @Table(name = "clients") public class Client { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(length = 32, nullable = false) private String firstName; @Column(length = 32, nullable = false) private String lastName; public Client(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } } @Getter @EqualsAndHashCode(of = "name") @ToString(of = {"name", "price"}) @NoArgsConstructor @Entity @Table(name = "items") public class Item { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, length = 32) private String name; @Columns( columns = { @Column(name = "price_currency", length = 3, nullable = false), @Column(name = "price_amount", precision = 7, scale = 2, nullable = false) } ) @Type(type = "org.jadira.usertype.moneyandcurrency.moneta.PersistentMoneyAmountAndCurrency") private Money price; public Item(String name, Money price) { this.name = name; this.price = price; } }
  • 19. www.luxoft.com 1 @Getter @EqualsAndHashCode(of = {"city", "street", "building"}) @ToString(of = {"city", "street", "building"}) @NoArgsConstructor @AllArgsConstructor @Embeddable public class Address { private String city; private String street; private String building; } @AllArgsConstructor public enum Status { NEW("N"), PROCESSING("P"), COMPLETED("C"), DEFERRED("D"); @Getter private final String code; } @Converter(autoApply = true) public class StatusConverter implements AttributeConverter<Status, String> { @Override public String convertToDatabaseColumn(Status status) { return status.getCode(); } @Override public Status convertToEntityAttribute(String code) { for (Status status : Status.values()) { if (status.getCode().equals(code)) { return status; } } throw new IllegalArgumentException( "Unknown code " + code ); } }
  • 20. www.luxoft.com 2 @Getter @EqualsAndHashCode(of = {"created", "client"}) @ToString(of = {"created", "address", "express", "status"}) @NoArgsConstructor @Entity @Table(name = "orders") public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) private LocalDateTime created = LocalDateTime.now(); @AttributeOverrides({ @AttributeOverride(name = "city", column = @Column(name = "address_city", nullable = false, length = 32)), @AttributeOverride(name = "street", column = @Column(name = "address_street", nullable = false, length = 32)), @AttributeOverride(name = "building", column = @Column(name = "address_building", nullable = false, length = 32)) }) private Address address; @Setter private boolean express; @Column(length = 1, nullable = false) @Setter private Status status = Status.NEW; @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST, optional = false) private Client client; @ElementCollection @Column(name = "quantity", nullable = false) @MapKeyJoinColumn(name = "item_id") @LazyCollection(LazyCollectionOption.EXTRA) private Map<Item, Integer> items = new HashMap<>(); }
  • 22. www.luxoft.com Check List 22 ● entities состоят из большого количества примитивных полей, а не из классов ● вместо enum-ов используются строковые константы ● методы equals/hashCode не определены ● в бизнес-логике и запросах фигурируют id ● происходит смешение Entity и Dto в одном классе ● использование FetchType.EAGER, в том числе по умолчанию в @ManyToOne ● ненужные вызовы flush() и clear() ● неаккуратное использование Lombok