Existe alguma forma de fazer o Hibernate usar o método SET preencher um bean ??
é que ele ta botando o dado diretamente no FIELD, ai não consigo autar com alguma regras de negocio
Existe alguma forma de fazer o Hibernate usar o método SET preencher um bean ??
é que ele ta botando o dado diretamente no FIELD, ai não consigo autar com alguma regras de negocio
Os dados que o Hibernate popula são aqueles provenientes do BD. Se os dados estão no BD, caso seu sistema esteja funcionando a contento, eles são válidos, por isso nao vejo problema em setar o field. Mas coloca o código do que exatamente vc quer fazer, quem sabe não surjam algumas idéias alternativas…
public class Pessoa implements IEntitySignature {
private static final long serialVersionUID = 2557413053448883151L;
private static final String ERRO1 = "Máximo permitido de 100 letras por nome.";
@Id @GeneratedValue private Integer id;
@Length(max=100,message=ERRO1) private String nome;
@Embedded @Length(max=11) private Cpf cpf;
//@ManyToOne private Cidade naturalidade;
}
public class Cpf {
@Column(unique=true) private String cpf = null;
@Transient private boolean isValid = false;
public Cpf(String cpf) {
setCpf(cpf);
}
public void setCpf(String cpf) {
this.cpf = cpf;
initialize(); //abstraia isso aqui, ele testa c o CPF é valido
//^^ não quero e não preciso salvar isso no banco
}
public boolean isValid() {
return isValid;
}
}
isValid é um teste, que faço quando vc cria um CPF ....
Não quero fazer o teste a cada chamada de isValid(), mais sim apenas 1 unica vez
.............
O hibernate preenche CPF diretamente via FIELD, sendo assim, ele não inicializa, o que estraga toda a brincadeira
Como pude perceber no seu código, é exatamente o caso em que o CPF virá do BD, e se ele foi inserido lá, é pq é válido, então acho que nao seria necessário fazer a validação novamente. Agora se vc relamente kiser fazer isso, uma gambiarra seria vc dar uma pesso.setCPF(pessoal.getCPF) sempre que fosse utilizar a classe. Realmente não sei se tem como pedir pro Hibernate setar as propriedades pelo método set. Eu nem sabia que ele fazia isso, uma vez que ele pede que as classes seja beans…
Como pude perceber no seu código, é exatamente o caso em que o CPF virá do BD, e se ele foi inserido lá, é pq é válido, então acho que nao seria necessário fazer a validação novamente. Agora se vc relamente kiser fazer isso, uma gambiarra seria vc dar uma pesso.setCPF(pessoal.getCPF) sempre que fosse utilizar a classe. Realmente não sei se tem como pedir pro Hibernate setar as propriedades pelo método set. Eu nem sabia que ele fazia isso, uma vez que ele pede que as classes seja beans...
o fato é que ja existem CPF no banco ^^ ... e como vinheram do incrivel .xls (excel) ele tem erros, e existem CPF invalidos...
porem estes CPF invalidos são muitas vezes bem proximo do original, as vezes faltando uma coisa ou outra, portanto foi decidido que os dados dos CPFs invalidos não serão jogados fora, sendo assim, preciso manter eles no banco....
mas resolvi assim@Transient private Boolean isValid = null;
//troquei de boolean para Boolean (agora pode ter null)
//.....
public boolean isValid() {
ensuresInitialize();
return isValid;
}
private void ensuresInitialize() {
if (isValid == null)
initialize();
}
Na vida há um jeitim pra tudo ^^
Bom a quem interessar possa....
Meu Object Value CPF
Cpf.javapackage org.lavieri.modeutil;
import java.math.BigInteger;
import javax.persistence.Column;
import javax.persistence.Transient;
import org.lavieri.util.StringUtil;
public class Cpf {
/*################################## Static Start #####################################*/
/**
* Retorna uma {@link String} contendo os 2 digitos Validadores para o {@link Cpf}
* Enviado. Para tal usa-se do teste estipulado pela Receita Federal.
* <BR>
* <BR>mais informações em: http://www.receita-fazenda.gov.br
* @see #getDigits()
* @see #isValid(Cpf)
* @param cpf O cpf ao qual deseja-se saber quais são os 2 digitos validadores.
* @return {@link String} contendo os 2 digitos que validam o CPF enviado.
*/
public static String digitValidator(Cpf cpf) {
String cpfString = cpf.toString();
long firstDigitSum = 0;
long secondDigitSum = 0;
for (int i = 0; i<10; i++) {
String s = cpfString.substring(i, i+1);
firstDigitSum += (10-i) * Integer.parseInt(s);
secondDigitSum += (11-i) * Integer.parseInt(s);
}
//firstDigitSum%11 é o mesmo que "Resto da divisão de firstDigitSum por 11"
long digit1 = ((firstDigitSum % 11) > 1) ? 11 - (firstDigitSum % 11) : 0;
long digit2 = ((secondDigitSum % 11) > 1) ? 11- (secondDigitSum % 11) : 0;
return "" + digit1 + digit2;
}
/**
* Verifica se o objeto {@link Cpf} enviado é um CPF válido, de acordo com o teste
* estipulado pela receita federal. Desconcidera para tal o CPF [CPF removido] único
* que atende os requisitos do teste, porem é dado como inválido, estipulado pela
* Receita Federal: http://www.receita-fazenda.gov.br
* @see #digitValidator(Cpf)
* @param cpf {@link Cpf} a ser testado.
* @return <tt>true</tt> caso o CPF seja válido
* <BR><tt>false</tt> caso o CPF seja inválido
*/
public static boolean isValid(Cpf cpf) {
return (cpf.equals("[telefone removido]")) ? false :
digitValidator(cpf).equals(cpf.getDigits());
}
/**
* Apenas um atalho, o mesmo que um dos dois comando abaixo:
* <BR><tt>(new {@link Cpf}(cpfString)).isValid()</tt>
*
* @see #isValid(Cpf)
* @param cpf String contendo o CPF a ser testado
* @return <tt>true</tt> caso o CPF seja válido
* <BR><tt>false</tt> caso o CPF seja inválido
*/
public static boolean isValid(String cpf) {
return (new Cpf(cpf)).isValid();
}
/**
* Poem mascaras de formatação no objeto CPF, retornando no formato
* <tt>___.___.-__</tt>
* <BR>Por exemplo:
* <BR><tt>cpf = new Cpf("[telefone removido]")
* <BR>Cpf.toFormated(cpf) //String de retorno = "[CPF removido]"</tt>
*
* @see #toFormated()
* @param cpf
* @return
*/
public static String toFormated(Cpf cpf) {
String cpfString = cpf.toString();
cpfString = String.format("%s.%s.%s-%s",
cpfString.substring(0, 3),
cpfString.substring(3, 6),
cpfString.substring(6, 9),
cpfString.substring(9, 11));
return cpfString;
}
/**
* Apenas um atalho, o mesmo que objetCpf.toLong()
* @see #toLong()
* @param cpf
* @return
*/
public static long toLong(Cpf cpf) {
return cpf.toLong();
}
/**
* Retira toda formatação existente na String enviada, removendo todos os caracters
* inválidos, e deichando apenas números.
* <BR>
* <BR>Caso a string restante seja inferior a 11 digitos, preenche os caracters
* restantes com "0"s a esquerda.
* <BR>
* <BR>Caso a string seja superio a 11 digitos ela será truncada para 11 digitos.
* @see StringUtil#toNumericDigitsOnly(String)
* @param cpf {@link String} a ser removida as formatações.
* @return {@link String} sem formatação, apeas com os digitos
*/
public static String toUnFormated(String cpf) {
cpf = (cpf == null) ? "" : StringUtil.toNumericDigitsOnly(cpf);
if (cpf.length()>11)
cpf = cpf.substring(0, 11);
else if (cpf.length()<11) //insert (11-length) "0"s before the cpf number
cpf = "[telefone removido]".substring(cpf.length(), 11) + cpf;
return cpf;
}
/*################################# Instance Start ####################################*/
/**
* O cpf deste objeto.
*/
@Column(unique=true) private String cpf = null;
/**
* Transiente value, não persistido no banco de dados, responde se este cpf é valido.
* é preciso ser resgatado via isValid(), para que possa ser inicializado o teste.
* <BR>O teste só é realizado uma única vez.
*/
@Transient private Boolean isValid = null;
/**
* Construtor nulo, cria um CPF invalido cujo o valor é [CPF removido]
*/
public Cpf() {}
/**
* Constroi um Cpf guardando seu valor em {@link #cpf}, qualquer que seja a string
* passada, ela será devidamente tratada.
* <BR>Todos os caracters invalidos serão removidos, sobrando apenas números, se
* faltar digitos para completar 11, serão incluidos "0" a esquerda da string.
* <BR>
* <BR>Invoca implicitamente {@link #toFormated(Cpf)}.
* <BR>
* <BR>O teste quanto a sua validação só é ralizado após {@link #isValid()} ser
* invocado, este teste só é realizado uma vez, e seu valor é guardado dentro do
* campo {@link #isValid}.
* @see #toUnFormated(String)
* @param cpf Objeto {@link Cpf} já construido.
*/
public Cpf(String cpf) {
this.cpf = cpf;
cpfInitializeted();
}
/**
* Constroi um objeto {@link Cpf} a partir de um {@link Long}
* @param cpf {@link Long} valor do cpf.
*/
public Cpf(Long cpf) {
this.cpf = (cpf == null) ? null : cpf.toString();
cpfInitializeted();
}
/**
* Constroi um objeto {@link Cpf} a partir de um {@link BigInteger}
* @param cpf {@link BigInteger} valor do cpf
*/
public Cpf(BigInteger cpf) {
this.cpf = (cpf == null) ? null : cpf.toString();
cpfInitializeted();
}
/**
* Inicializa o valor do CPF, formantando-o adequadamente.
*/
private void cpfInitializeted() {
if (cpf == null)
cpf = "";
else
cpf = cpf.trim();
this.cpf = toUnFormated(cpf);
}
/**
* Garante que {@link #cpfInitializeted()} já foi invocado previamente, invocando-o
* caso preciso.
*/
private void ensuresCpfInitializeted() {
if (cpf == null)
cpfInitializeted();
}
/**
* Garante que a variável {@link #isValid} já foi setada, via teste do cpf.
*/
private void ensuresWasValidated() {
if (isValid == null)
validateInitialize();
}
/**
* Testa se o cpf é valido.
*/
private void validateInitialize() {
isValid = isValid(this);
}
/**
* Verifica se 2 Cpfs são igauis, é capaz de testar se um objeto {@link Cpf} é igual
* a uma string contendo um valor de um Cpf não formato, apenas com numeros digitos.
* @return <tt>true</tt> caso o objeto enviado tenha o mesmo cpf deste
* <BR><tt>false</tt> caso os Cpfs sejam distintos.
*/
public boolean equals(Object obj) {
ensuresCpfInitializeted();
boolean equals = false;
if (obj instanceof String)
equals = obj.equals(cpf);
else if (obj instanceof Cpf)
equals = ((Cpf)obj).toString().equals(cpf);
return equals;
}
/**
* Retorna os 2 ultimos digitos do {@link Cpf}.
* <BR>
* <BR>É importante lembrar que esse método retorna os 2 últimos digitos reais do
* CPF enviado, onde estes não são necessáriamente os mesmos de
* <tt>{@link Cpf#digitValidator(Cpf)}</tt>, quando estes 2 são coincidentes,
* indica que este CPF é valido, caso contrário o CPF é inválido.
* @see #digitValidator(Cpf)
* @return {@link String} contendo os 2 ultimos dígitos do CPF.
*/
public String getDigits() {
ensuresCpfInitializeted();
return cpf.substring(9, 11);
}
/**
* Indica se este cpf é ou não valido. Este teste só é verificado internamente uma
* vez, podendo este método ser invocado sem perda de desempenho.
* @return <tt>true</tt> - Quando o cpf é valido
* <BR><tt>false</tt> - Caso contrario.
*/
public boolean isValid() {
ensuresWasValidated();
return isValid;
}
/**
* Converte esse CPF em um {@link BigInteger}
* @return
*/
public BigInteger toBigInteger() {
ensuresCpfInitializeted();
return new BigInteger(cpf);
}
/**
* Poem mascaras de formatação no objeto CPF, retornando no formato
* <tt>___.___.-__</tt>
* <BR>Por exemplo:
* <BR><tt>cpf = new Cpf("[telefone removido]")
* <BR>Cpf.toFormated(cpf) //String de retorno = "[CPF removido]"</tt>
*
* @see #toFormated()
* @param cpf
* @return
*/
public String toFormated() {
ensuresCpfInitializeted();
return toFormated(this);
}
/**
* Retorna um <tt>long</tt> que representa o valor deste cpf, porem todos os "0"s a
* esquerda do número do cpf será apagado
* <BR>
* <BR>Por exemplo:
* <BR><tt>long teste = (new Cpf("[CPF removido]")).toLong();
* <BR>{@link System#out}.println(teste); //saido do console = 103423200</tt>
* @return {@link Long} com o valor deste cpf.
*/
public long toLong() {
ensuresCpfInitializeted();
return Long.parseLong(cpf);
}
/**
* Retorna o valor deste cpf em forma de {@link String}, sem formatações.
* @return
*/
public String toString() {
ensuresCpfInitializeted();
return cpf;
}
}
A classe que ele depende é uma que só tem um método simples... de StringUtil
StringUtil.javapackage org.lavieri.util;
public class StringUtil {
public static String toNumericDigitsOnly(String s) {
return s.replaceAll( "\D*", "" );
}
}