OneToMany com Hibernate JPA

Opa! Pessoal,

O post de hoje vou apresentar como criar o relacionamento oneToMany / ManyToOne de forma simples. Quem ai nunca passou por algum tipo de problema ao criar esse tipo de relacionamento? Algo como de não criar a FK e só persistir uma das tabelas etc. Estarei apenas focando em como definir os relacionamentos à nível de código e para isso teremos code apenas para o objetivo do post. Quero evitar posts grandes sem necessidade.

lets go…

Required

– Vou assumir que se você está lendo este post é pq já está brincando com o Hibernate e agora precisa fazer um relacionamento entre as suas tabelas, então parte de configuração do framework, ou explicação dos métodos serão omitidos, qualquer dúvida consulte outros posts no blog na categoria Hibernate, e veja como ter o ambiente funcionando.

– A classe DAO nos códigos é que possui o trabalho de persistência, ela não é requirida para o post, pois vc uma vez que podemos obter o begin(), save(), commit() etc do hibernate por diversas formas.

– Hibernate 3.x

– MySql 5

OneToMany

O relacionamento OneToMany é bem usado, e são poucas vezes que de fato não precisamos te-lo, então é aquele lance se não precisou até hoje, espere mais um pouco que essa necessidade vai nascer. Vamos tirar a vantagem dos annotations e veremos @OneToMany e @ManyToOne ao invés dos .hbm, Como exemplo há vários cenários para exemplificar este tipo de relacionamento, tais como: um time de futebol tem vários jogadores, uma infra-estrutura tem vários servidores, porém um jogador só pode jogar em um time(ou não depende da regra de negócio, aqui está o pulo do gato), e um servidor está em uma infra-estrutura.

Note: Há casos que um jogador joga mais de um time, daí temos o ManyToMany.

Para criar esse tipo de relacionamento temos que identificar o ponto chave do relacionamento entre as classes, como por exemplo, para um Time de futebol, temos que saber que há uma lista com os jogadores que pertencem ao clube, uma vez que um team não tem apenas 1 jogador este pode ter de 0..X(mesmo sem jogadores ele pode ser considerado um team de futebol, mas está sem grana e demitiu todos os jogadores). Eu costumo chamar de HAS-AN List something (tem uma lista de alguma coisa).

A seguir temos a class bean que representa o Team (por boas práticas elas não deveria extends DAO, porém fiz aqui para ser mais pratico e fazer sentindo com as invocações do Hibernate que temos no code).

@Entity

public class Team extends DAO{

@Id

@GeneratedValue

private long id;

@Column

private String nameTeam;

private List<Player> players;

Usando @OneToMany

Agora vamos usar o relacionamento apropriado para a classe,a seguir temos o code atualizado:

@Entity

public class Team {

private String nameTeam;

@OneToMany(mappedBy = “team”, targetEntity = Player.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)

private List<Player> players;

mappedBy = informamos o nome da variavel de instância que vai indicar a quem aquele One pertence, ou seja, um jogador ele deve dizer a qual time este está associado.

TargetEntity = informa qual a entidade estamos associando

FetchType.Lazy = foi escolhido por performace

cascade = ALL para permitir alterações em todos os relacionamentos.

Pronto, já dizemos que um TEAM tem muitos jogadores (uma lista )

Usando @ManyToOne

Na classe que representa o MANY(do manyToOne), que nesse caso é a Player, teremos uma anotação @ManyToOne na variavel de instancia que representa o TEAM.

@Entity

public class Player {

@Id

@GeneratedValue

private long id;

private String nickName;

@ManyToOne

@JoinColumn(name=“team_id”)

private Team team;

@JoinColumn = informamos o nome que terá o FK.

Ao rodar o código main na class Team:

public static void main(String args[]) {

Team team1 = new Team();

team1.setNameTeam(“São Paulo”);

Player jogador1 = new Player();

Player jogador2 = new Player();

jogador1.setNickName(“Rogerio Ceni”);

jogador2.setNickName(“Luiz Fabiano”);

// has-an associando o jogador ao team

jogador1.setTeam(team1);

jogador2.setTeam(team1);

begin();

getSession().save(team1);

getSession().save(player1);

getSession().save(player2);

commit();

}

Talvez você tenha pensado que apenas 1 (um) save() seria necessario, mas não é, pois precisamos colocar a instancia dos players com a session, para que este se torne um objeto persistente do contrario, o Hibernate não o poder de persistir no banco. O resultado:

O team do São Paulo tem dois jogadores, observe que o ID do team aparece na table do Player(team_id) assim sabemos a qual time este pertence.

Erros comuns durante a programação:

  • esquecer de associar as instâncias envolvidas no relacionamento, se eu esquecer de dizer a qual team um jogador pertence, não teremos o resultado esperado e o resultado na sua tabela será NULL, caso seja permitido esse valor na coluna.

  • Não salvar as instâncias que serão persistidas é outro fato comum, quem está fazendo pela primeira acredita que dar um save apenas na classe que representar One (team), é o sufuciente e por alguma mágina o Hibernate vai saber quais outras instancias devem ser persistidas, ai vem a pergunta, como o Hibernate vai saber, se você não transformou o “objeto java” criando em um objeto-persistent?

Espero que tenham gostado do post, vou ficando por aqui.

Abracos see you next post!!! 🙂

Criando JAR com MySQL,Hibernate e Quartz

olá pessoal,

O post de hoje é algo bem iniciante, mas ainda muito usado quando estamos trabalhando com protipo de algo e precisamos apenas validar se uma solução vai funcionar de fato. Ou seja, quando estamos na ponta do iceberg. Então hoje, vou mostrar como criar um arquivo JAR pelo Eclipse, mas não será um arquivo JAR qualquer com um “Hello World” apenas, este terá que connectar à um banco de dados MySQL e ainda o Quartz. Então somente neste contexto temo três APIs externas no aplicativo, pois o Hibernate fará o terceiro.

Lets go…

Alguns requisitos:

  • ter o hibernate configurado, dúvidas consulte outros posts do Hibernate aqui.
  • ter todas as libs no projeto
  • antes de criar o JAR, certifique-se que tudo funciona no modo de DEV(hibernate, conexão com banco etc. Rode e check os resultados inúmeras vezes;
  • tenha o MySQL 5/superior instalado;

Starting…

Vamos dizer que você precise mostrar a funcionalidade de algo da maneira mais simples possível, e quem for ver está mais preocupado na funcionalidade do que em layout, performance (por enquanto). Como trabalho com pesquisa e desenvolvimento tenho passado por isso com bastante frequência, uma vez que no inicio de algo estamos no prototipo para uma possível nova feature, solução, seja o que for, mas não é legal no inicio gastar muita energia, com performance, layout, ou qualquer caracteristica que não agrega valor na funcionalidade. Caso a ideia não seja válida, o resultado será que gastei menos energia e tempo. E já foi possível descartar.

Situação

Um dia desses tive que apresentar uma solução para uma feature do projeto que, nem sabiamos se ia dar certo e como seria os impactos. Daí começamos com as investigações e pesquisa necessária, e quando fomos apresentar para os arquitetos, o team de Q.A etc. Foi algo bem produtivo porque geramos um JAR com o banco HSQLDB, distribuimos esse JAR e eles só executaram e viram o resultado desejado (não posso dar maiores detalhes). Já pensou se fosse necessário ter que montar todo o ambiente de DEV na maquina de quem fosse validar a solução? Exemplo: de ter que instalar um banco real, configurar os acessos etc. Bem, nada produtivo né?

HSQLDB: é um banco em Java que não passa de JAR e que por sinal é bem completinho, porém com suas limitações e não queira comparar ele com MySQL, SQL Server, Oracle etc . Basta adicionar o .jar ao seu projeto e terá o HSQLDB disponível para receber os dados. Claro que terá que informar ao hibernate.cfg.xml sobre isso. Qualquer dúvida, basta dar uma “googlada” que encontrará vários posts a respeito de como usar o HSQLDB. A documentação também ajuda: http://hsqldb.org/ http://pt.wikipedia.org/wiki/HSQLDB

 

Note

Aqui vamos usar o MySQL 5 então vou levar em conta que você já tem ele instalado na sua maquina. Também, acredito que já tem o projeto do ultimo post rodando. Mas, caso não tenha use qualquer outro projeto pessoal que tenha acesso à um banco de dados, que use o hibernate, para ficar bem próximo do nosso.

Development

Eu poderia ter ido direto ao ponto e ter feito o post com 3,4,5 linhas, mas sempre gosto de fazer um contexto, para quem está lendo possa ter uma ideia da utilização, principalmente se está vendo o assunto pela primeira vez, é mais importante ainda, pois saber o porque das coisas é tão importante quando saber fazer. Não saia fazendo, por fazer. Sempre se pergunte o por que fazer isso?

  • uma vez com o projeto criado no eclipse, clique com o botão direito e escolha build path → configure build path.
  • agora precisamos informar as libs que serão exportadas

observe que marquei as bibliotecas que preciso. No caso do nosso exemplo são: hibernate, quartz e mysql.

  1. Clique em ok
  2. agora clique com o botão direito no projeto e escolha export
  3. procure pela pasta Java
  4. e escolha Runnable JAR e clique em next

  1. agora precisamos informar o projeto, que no caso será QuartzDBHibernate

  1. indique o local que deseja salvar seu arquivo JAR.
  2. Clique em finish e aguarde terminar (talvez apareça um warning, se quiser clique em details leia e prossiga. Não é nada critico)

Uma vez com JAR gerado, vamos testar a execução. No caso do windows abra o promt de comando e navegue até onde salvou o seu JAR. E digite: java -jar quartzdbHibernate.jar (eu usei o mesmo nome do projeto, você deve informar o nome que deu ao arquivo JAR caso tenha sido diferente).

 

Agora vamos ver o resultado, ahh não esqueça de dar um START no seu MySql do contrário verá exceções na tela.

Observe que foi adicionado o usuario, o sql é printed  pelo hibernate uma vez que configurei no hibernate.cfg.xml para ser impresso. Agora vamos  ao  banco.

Na imagem acima temos o banco atual e veja que o ultimo ID é 60. na imagem a seguir temos o banco atualizado e o ultimo ID é 61:

 

Alguns profissionais “Senior”  crucificaria o Camilo por fazer um post deste tipo, tão ABC.  Mas, como sempre falei : “todo sênior hoje um dia deu hello world, e passou pelas mesmas dificuldades que alguem que está chegando hoje no mundo java está passando, e com certeza  esse senior precisou de ajuda, e pq ignorar de dar essa ajuda hj ?”. O que tenho aprendido nesses 3 anos como blogueiro  foi o seguinte: o mais prazeroso  não é escrever um post “avançadao ou basicao” para querer mostrar que “sabe” algo. E sim saber, o que foi escrito teve um impacto positivo na vida do leitor  independente do nível do post. Até hoje  lembro das noites em claro que passei, para instalar e configurar o Java corretamente no windows, e a dificuldade que tive em fazer isso de forma automatica, sem precisar “googlar” fazer aquele javac funcionar era osso. E quando conseguir, virou meu primeiro post do blog, e foi onde tudo começou. E até tenhoo leitores comentando que o post tem salvado o dia deles.

Vou ficando por aqui e espero que tenham gostado do post.

abracos see you next post!!!

Usando quartz com o Hibernate

opa! Pessoal,

O post de hoje vou apresentar API Quartz. O objetivo é mostrar como Quartz é simples de usar. E para contexto, escolhi que criaremos um job, que terá como trabalho de popular um banco a cada X time, que nesse caso vamos usar o Hibernate para fazer esse tramapo. O Quartz nada mais é que um scheduler de jobs, que podem ser executados em momento determinados. No decorrer do post veremos mais na prática.

Lets go…

Para usar o quartz basta fazer download do jars(quartz-all.x.jar) e adicionar ao projeto. Adicione as libs do Hibernate e Banco de dados (aqui usaremos o MySQL) ao projeto também.

API QUARTZ: http://www.quartz-scheduler.org/

*Caso tenha dúvida sobre o Hibernate, veja os nossos posts na categoria.

Desenvolvimento

Para usar quartz vamos criar um package br.com.camilolopes.scheduler neste packages teremos uma classe responsavel por executar os jobs programados.

No package br.com.camilolopes.job é onde temos a classe que tem um trabalho a ser feito, que no nosso caso é persistir no banco de dados.

Package br.com.camilolopes.dao tem as configurações para o Hibernate que não está atrelado ao quartz.

Primeiro passo

É começar com a classe SchedulerJobs no package br.com.camilolopes.scheduler onde vamos definir os jobs a serem executados e o time para eles. Como esta classe será a principal, ela terá o método main.

 

package br.com.camilolopes.scheduler;

import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerUtils;
import org.quartz.impl.StdSchedulerFactory;
import br.com.camilolopes.job.PersistDB;

/*
* esse é o agendador de jobs
*/
public class SchedulerJobs {

public SchedulerJobs() {
// TODO Auto-generated constructor stub
}
public static void main(String[]args) {

//neste caso a cada 1 min
Trigger trigger = TriggerUtils.makeSecondlyTrigger(30);
trigger.setName(“jobdb”);
/*dou informacoes qual classe ele deve chamar
ou seja, o trabalho a ser feito
*/
JobDetail jobDetail = new JobDetail(“save db”, PersistDB.class);
try{
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
//info o job a ser feito e de em qto em qto tempo passando o trigger
scheduler.scheduleJob(jobDetail, trigger);
//peco para iniciar
scheduler.start();
}catch (SchedulerException e) {
e.printStackTrace();
}

}
}

Trigger = esta classe é responsável por configurar o tempo em que cada job será executado, nesse caso configuramos para a cada 30s. Veja que usamos a classe TriggerUtils. Que já possui alguns metodos implementados e não vamos precisar reiveitar a roda. Em seguida damos um nome para esse trigger.

JobDetail = é aqui que temos o job a ser executado nesse caso mandamos executar o job que está na classe PersistDB.class, veja que damos um nome para esse nome.

Scheduler = aqui onde temos uma instancia de um scheduler que será responsavel por executar o job, e como criamos uma instancia de uma factory, precisamos apenas informar o job e o tempo que ele vai ser executado nesse caso, é vai a variavel de JobDetail e o time que definimos em Trigger. Para iniciar o job chamamos o metodo start().

Na classe a serguir temos o trabalho a ser feito que é criar um usuario e chamar o método save() responsável por fazer o trabalho de persistência no banco de dados.

public class PersistDB implements Job{

@Override

publicvoid execute(JobExecutionContext arg0) throws JobExecutionException {

UsuarioQuartzDao usuariodao = new UsuarioQuartzDao();

Usuario usuario = new Usuario();

usuario.setEmail(“camilo@”);

usuario.setNome(“lopesff”);

usuario.setSenha(“123”);

usuario.setTipo(“admin”);

usuariodao.save(usuario);

System.out.println(new Date());

}

}

A classe que possui o job a ser feito precisa implementar a interface Job e colocar o trabalho dentro do metodo execute().

Classe DAO.

public class UsuarioQuartzDao extends DAO {

public void save(Usuario us){

begin();

getSession().save(us);

try{

commit();

}catch (Exception e) {

e.printStackTrace();

}}

}

Na classe acima é onde ocorre a persistencia com o banco usando o Hibernate, um detalhe que quero chamar atencao é pedi para o Hibernate criar a table e a cada vez que o job rodar ele não criar uma nova table e sim adicionar apenas os dados, para isso seu arquibo hibernate.cfg.xml deve ter um update no hb2mddl.auto como update, se não existir ele cria de forma automatica.

<property name=“hibernate.hbm2ddl.auto”>update</property>

O code completo:

<property name=“hibernate.connection.driver_class”>org.gjt.mm.mysql.Driver</property>

<property name=“hibernate.connection.password”>blog</property>

<property name=“hibernate.connection.url”>jdbc:mysql://localhost/blogleitores</property>

<property name=“hibernate.connection.username”>camilolopes</property>

<property name=“hibernate.dialect”>org.hibernate.dialect.MySQL5InnoDBDialect</property>

<property name=“hibernate.show_sql”>true</property>

<property name=“hibernate.current_session_context_class”>thread</property>

<property name=“hibernate.transaction.factory_class”>org.hibernate.transaction.JDBCTransactionFactory</property>

<property name=“hibernate.hbm2ddl.auto”>update</property>

<mapping class=“br.com.camilolopes.bean.Usuario”/>

 

Resultado

Ao executar o code, temos os resultado conforme a seguir:

 

 

Observe que o Job é executado dentro do tempo e o trabalho de persistir de fato acontece. Um fato que identifiquei é que se o job, demorar mais que o tempo configurável o próximo job, tem que aguardar o outro finalizar para iniciar o trabalho dele. Outro ponto se configurarmos o método shutdown (true) e colocar depois do método estar, assim após o termino de todos os jobs, o scheduler é “desligado” e os trabalhos não mais reiniciados. No nosso exemplo ele roda de maneira infinita.

scheduler.start();

scheduler.shutdown(true);

Vou ficando por aqui e espero que tenham gostado do post, eu tenho usado o quartz em algumas soluções no meu job e de fato é uma API excelente. Além de uma boa documentação, o fórum é bem ativo para tirar duvidas.

Abraços, see you next post. 😀

AnnotationsConfiguration Deprecated Hibernate 3.6

opa! Pessoal,

O post de hoje é bem pequeno, porém importante para quem for usar o Hibernate 3.6/superior. Venho utilizando o versao 3.2 por um bom tempo devido aos projetos que tenho atuado  está usando a 3.2. Daí surgiu um novo projeto e então na definição optei em usar a versão mais recente e estável o Hibernate 3.6.x confesso que não tenho acompanhado os release de cada versão e ao usar descubro mudanças à nível de code, principalmente da forma que faziamos na 3.2  uma delas foi com o new AnnotationConfiguration() e hoje vamos ver o que mudou.

Lets go…

Saiba mais: www.hibernate.org

Starting

Aqui no blog há vários posts usando Hibernate com AnnotationsConfiguration. Mas, para quem estiver com a versão mais recente do Hibernate terá que mudar apenas uma linha de código, pois a classe AnnotationsConfiguration que era filha de Configuration foi deprecated pelo team do Hiberante, então nada de informar que vai usar annotations usando essa classe, agora é com a classe pai Configuration.

Os Impactos

Não é um impacto muito grande, uma vez que vai precisa apenas alterar uma linha do seu código, caso você venha da versão 3.2 para 3.6. Porém, o esquecimento de alterar o código e somente adicionar as os novos .jars , farão seu build quebrar :).

Na Pratica

A seguir mostro a forma na versão 3.2 e 3.6 que você vai alterar no seu DAO.

Versão 3.2

public class DAO {

private static final SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();

//mais code

}

Versão 3.6

public class DAO {

private static final SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

//mais code

}

Espero que tenham gostado da dica, mas é vivendo e aprendendo, principalmente quando não acompanhamos as releases, hehe.

Vou ficando por aqui, see you next post.

Abracos,

Criteria Hibernate parte II

opa! Pessoal,

Neste post veremos mais algumas restrições importantes que temos na API Criteria. Não deixarei de apresentar os codes, mais ainda não faremos nada pratico com o BD, reservei este momento para um outro post, onde vamos “respirar” toda série de modo mais prático em um único post, e focar mais no entendimento e uso do Criteria. Principalmente se você está começando agora nada melhor que ir passo-passo.

Lets go…

note: Uma coisa é certa: Quer aprender e melhorar seus conhecimentos? use a documentação, ela é tão explicativa quanto um tutorial passo-passo, uma das melhores documentações que já li, e o segredo não é decorar e sim ir implementado com base nas necessidade, crie situações (caso não tenha) e vá implementado aos poucos, quando menos esperar já vai está dominando as principais. Essa é minha dica. 🙂

Restrições com Criteria API

Uma outra restrição bem legal é o uso do >=, >, <=,< que fazemos no SQL,HQL etc. No Criteria temos métodos que nos ajudam na implementação desses operadores: gt(),ge(),lt(),le().

  • gt() = maior que

  • ge() = maior ou igual que

  • lt() = menor que

  • le() = menor ou igual que

Saber de onde os métodos pertencem é tão importante quando saber usá-los. Os citados acima vem da classe Resctrictions. Exemplo:

crit.add(Restrictions.ge(“preco”, new Double(100.00));

A leitura é bem simples: retorna todos os produtos com o preço maior ou igual 100.00. um dos pontos importante no uso de Criteria é quando precisamos usar AND e OR nas restrições.

crit.add(Restrictions.gt(“preco” new Double(100.0));

crit.add(Restrictions.like(“nome”, “smart%”));

List lista = crit.list();

A leitura é a seguinte: retorne produtos com o preco maior que 100.0 e (AND) que tenha o nome “smart” como parte da String.

Agora se precisarmos do OR, veja como fica:

Criterion preco = Restrictions.gt(“preco”, new Double(100.0));

Criterion nome = Resctrictions.like(“nome”, “smart%”);

LogicalExpression orExp = Resctrictions.or(preco,nome);

crit.add(orExp);

List list = crit.list();

A lógica é a seguinte: retorne produtos com preco maior que 100.0 ou que tenha “smart” na palavra. Na linha 4 adicionamos o resultado. Então a linha 2 somente é executada caso a primeira seja falsa.

Quando queremos mais que duas diferentes sequencias de OR poderíamos usar a classe Disjunction que fica em org.hibernate.Disjunction para representar uma disjunction. Sem sombras de duvidas usar disjunction é mais conveniente que vários OR no código, veja como fica:

Criterion preco = Resctrictions.gt(“preco”, new Double(100.0));

Criterion nome = Resctrictions.like(“nome”, “smart%”);

Criterion fornecedor = Restrictions.like(“fornecedor”, “nokia%”);

Disjunction dis = Resctrictions.disjunction();

dis.add(preco);

dis.add(nome);

dis.add(fornecedor);

cri.add(dis)

List lista = crit.list();

A leitura do código acima seria:

Retorne os produtos que tenha o preço maior que 100.0 ou (or) que tenha na parte da string a palavra “smart” ou que tenha na propriedade fornecedor a palavra “nokia”. Para fazer com o AND usamos o método conjunction() da classe Resctrictions.

Conjunction conj = Restrictions.conjuction();

Apenas alteramos de disjunction  para  a linha acima e assim temos a  clausula AND.

Vou ficando por aqui e espero que tenham gostado do post que foi simples e rápido.

See you next post, guys!!

abracos,