DEV Community

EronAlves1996
EronAlves1996

Posted on

Evite redundâncias ao definir Entities do JPA

Se você for definir uma tabela, por favor, não faça isso!

Image description

Vamos saber melhor por que!

No JPA, uma classe é mapeada para uma tabela através da anotação @Entity. Com essa anotação nós indicamos que a classe é uma entidade do JPA, nesse caso, automaticamente ele mapeia a classe para uma tabela.

Para isso, o JPA está configurado por default a resolver o nome da classe para uma tabela da seguinte forma:

1 - Classes no Java são definidas através de PascalCase.
2 - O nome da classe é convertida em snake_case.
3 - Este nome convertido é utilizado para o nome da tabela no banco de dados.

Então, através desse algoritmo:

CustomerDetails -> customer_details
Enter fullscreen mode Exit fullscreen mode

No caso do exemplo original:

Product -> product
Enter fullscreen mode Exit fullscreen mode

Só isso já conseguimos eliminar a necessidade da anotação @Table.

Conseguimos também definir o nome da tabela ao definir o nome da entidade nas queries JPQL. Isso porque o nome da tabela é resolvido através do seu nome nas queries. Primeiro, por default, é resolvido pelo nome da classe da entidade, porém podemos mudar esse nome pela anotação @Entity:

@Entity(name = "blablabla")
Enter fullscreen mode Exit fullscreen mode

Só fazendo isso, conseguimos mudar o nome da tabela que será mapeada e de quebra também o nome que iremos utilizar para as queries JPQL.

Podemos ter edge cases para definir as duas anotações, que é quando a tabela tem um nome específico, e nas queries JPQL iremos nos referir ao nome da classe mesmo, exemplo:

@Entity
@Table(name="products")
public class Product {

}
Enter fullscreen mode Exit fullscreen mode

No caso aqui, o nome da tabela está no plural, porém na query JPQL, iremos utilizar o nome da classe mesmo:

@Query("Product p where p.vendorId = :vendorId")
Product findProductFromVendor(int vendorId);
Enter fullscreen mode Exit fullscreen mode

Neste caso, a query que isso irá gera no SQL será o seguinte:

SELECT * FROM products WHERE vendor_id = 10
Enter fullscreen mode Exit fullscreen mode

Outro edge case seria se eu quisesse que o nome da entidade nas queries seja diferente do nome da classe e o nome na tabela seja diferente dos dois:

@Entity(name="prod")
@Table(name="products")
public class Product{

}
Enter fullscreen mode Exit fullscreen mode

É essencial entender o funcionamento das anotações e do framework que estamos utilizando para não cairmos em redundância desnecessária na hora de programar!

Top comments (1)

Collapse
 
wldomiciano profile image
Wellington Domiciano

Oi, Eron. Vc se confundiu ao descrever o comportamento padrão do JPA.

O JPA, por padrão mapea para tabelas no banco de dados com o mesmo nome da entidade.

O exemplo abaixo mapeará para uma tabela chamada CustomerDetails, pois o nome da entidade, por padrão, é o unqualified name da classe, e não "customer_details" como vc disse.

@Entity class CustomerDetails { /* ... */ }
Enter fullscreen mode Exit fullscreen mode

O que vc descreveu como sendo o comportamento padrão do JPA, na verdade é o comportamento oferecido pela PhysicalNamingStrategy CamelCaseToUnderscoresNamingStrategy do Hibernate e que é o padrão em aplicações que usam Spring Boot.


Anotar Product com @Table(name = "product") não é bem uma redundância desnecessária, já que ela assegura que o nome da tabela esteja como esperado independente da PhysicalNamingStrategy utilizada em caso de uma mudança brusca no Spring Boot ou mesmo de uma migração para outro framework.

Além disso, eu não diria que seu exemplo com @Table(name="products") é um edge case já que é extremamente comum encontrar tableas nomeadas no plural ou mesmo com prefixos como "tbl_".