Respostas:
@Transient
está em conformidade com suas necessidades.
Para ignorar um campo, anote-o com, @Transient
para que não seja mapeado pela hibernação.
mas jackson não serializará o campo ao converter para JSON.
Se você precisar misturar JPA com JSON (omitir JPA, mas ainda incluir em Jackson), use @JsonInclude
:
@JsonInclude()
@Transient
private String token;
DICA:
Você também pode usar JsonInclude.Include.NON_NULL e ocultar campos no JSON durante a desserialização quando token == null
:
@JsonInclude(JsonInclude.Include.NON_NULL)
@Transient
private String token;
@JsonInclude
não é necessário: os @Transient
campos ainda estão incluídos no JSON. (Você ainda recebeu meu voto: a técnica em si pode ser muito útil em outras circunstâncias).
Para ignorar um campo, anote-o com, @Transient
para que não seja mapeado pela hibernação.
Fonte: anotações de hibernação .
Essa resposta chega um pouco tarde, mas completa a resposta.
Para evitar que um campo de uma entidade seja persistido no DB, pode-se usar um dos dois mecanismos:
@Transient - a anotação JPA que marca um campo como não persistente
palavra-chave transitória em java. Cuidado - usar esta palavra-chave impedirá que o campo seja usado com qualquer mecanismo de serialização do java. Portanto, se o campo precisar ser serializado, é melhor usar apenas aanotação @Transient .
Existem várias soluções, dependendo do tipo de atributo da entidade.
Considere que você tem a seguinte account
tabela:
A account
tabela é mapeada para a Account
entidade assim:
@Entity(name = "Account")
public class Account {
@Id
private Long id;
@ManyToOne
private User owner;
private String iban;
private long cents;
private double interestRate;
private Timestamp createdOn;
@Transient
private double dollars;
@Transient
private long interestCents;
@Transient
private double interestDollars;
@PostLoad
private void postLoad() {
this.dollars = cents / 100D;
long months = createdOn.toLocalDateTime()
.until(LocalDateTime.now(), ChronoUnit.MONTHS);
double interestUnrounded = ( ( interestRate / 100D ) * cents * months ) / 12;
this.interestCents = BigDecimal.valueOf(interestUnrounded)
.setScale(0, BigDecimal.ROUND_HALF_EVEN).longValue();
this.interestDollars = interestCents / 100D;
}
//Getters and setters omitted for brevity
}
As propriedades básicas da entidade são mapeados para as colunas da tabela, assim como propriedades id
, iban
, cents
são atributos básicos.
Mas a dollars
, interestCents
e interestDollars
são propriedades calculado, para que anotá-los com @Transient
a excluí-los de SELECT, INSERT, UPDATE e instruções SQL DELETE.
Portanto, para atributos básicos, você precisa usar
@Transient
para excluir uma determinada propriedade da persistência.Para mais detalhes sobre atributos de entidade calculados, consulte este artigo .
Supondo que você tenha o seguinte post
e post_comment
tabelas:
Você deseja mapear a lastestComment
associação na Post
entidade para a PostComment
entidade mais recente que foi adicionada.
Para fazer isso, você pode usar a @JoinFormula
anotação:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
private Long id;
private String title;
@ManyToOne(fetch = FetchType.LAZY)
@JoinFormula("(" +
"SELECT pc.id " +
"FROM post_comment pc " +
"WHERE pc.post_id = id " +
"ORDER BY pc.created_on DESC " +
"LIMIT 1" +
")")
private PostComment latestComment;
//Getters and setters omitted for brevity
}
Ao buscar a Post
entidade, você pode ver que ela latestComment
foi buscada, mas se você quiser modificá-la, a alteração será ignorada.
Portanto, para associações, você pode usar
@JoinFormula
para ignorar as operações de gravação enquanto ainda permite a leitura da associação.Para mais detalhes sobre associações computadas, consulte este artigo .
Outra maneira de ignorar associações que já estão mapeadas pelo identificador de entidade é usar @MapsId
.
Por exemplo, considere o seguinte relacionamento de tabela um para um:
A PostDetails
entidade é mapeada assim:
@Entity(name = "PostDetails")
@Table(name = "post_details")
public class PostDetails {
@Id
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
private Post post;
public PostDetails() {}
public PostDetails(String createdBy) {
createdOn = new Date();
this.createdBy = createdBy;
}
//Getters and setters omitted for brevity
}
Observe que o id
atributo e a post
associação mapeiam a mesma coluna do banco de dados, que é a post_details
coluna Chave Primária.
Para excluir o id
atributo, a @MapsId
anotação informará ao Hibernate que a post
associação cuida do valor da coluna Chave Primária da tabela.
Portanto, quando o identificador de entidade e uma associação compartilham a mesma coluna, você pode usar
@MapsId
para ignorar o atributo identificador de entidade e usar a associação.Para mais detalhes
@MapsId
, consulte este artigo .
insertable = false, updatable = false
Outra opção é usar insertable = false, updatable = false
para a associação que você deseja que o Hibernate ignore.
Por exemplo, podemos mapear a associação individual anterior como esta:
@Entity(name = "PostDetails")
@Table(name = "post_details")
public class PostDetails {
@Id
@Column(name = "post_id")
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne
@JoinColumn(name = "post_id", insertable = false, updatable = false)
private Post post;
//Getters and setters omitted for brevity
public void setPost(Post post) {
this.post = post;
if (post != null) {
this.id = post.getId();
}
}
}
Os atributos insertable
e updatable
da @JoinColumn
anotação instruirão o Hibernate a ignorar a post
associação, pois o identificador da entidade cuida da post_id
coluna Chave Primária.
post
e post_details
tabelas como exemplo?
Nenhuma das respostas acima funcionou para mim usando o Hibernate 5.2.10, Jersey 2.25.1 e Jackson 2.8.9. Finalmente encontrei a resposta (mais ou menos, eles fazem referência ao hibernate4module, mas funciona para 5 também) aqui . Nenhuma das anotações de Json funcionou @Transient
. Aparentemente, o Jackson2 é 'inteligente' o suficiente para ignorar gentilmente as coisas marcadas com, a @Transient
menos que você diga explicitamente que não. A chave era adicionar o módulo hibernate5 (que eu estava usando para lidar com outras anotações do Hibernate) e desativar o USE_TRANSIENT_ANNOTATION
recurso no meu aplicativo Jersey:
ObjectMapper jacksonObjectMapper = new ObjectMapper();
Hibernate5Module jacksonHibernateModule = new Hibernate5Module();
jacksonHibernateModule.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);
jacksonObjectMapper.registerModule(jacksonHibernateModule);
Aqui está a dependência do Hibernate5Module:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
<version>2.8.9</version>
</dependency>
@JsonProperty
@JsonInclude
@JsonSerialize + @JsonDeserialize
mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, false));
essa solução finalmente funcionou. Obrigado!