[RESOLVIDO] Hibernate nao cria coluna(s)

Pessoal, estou com um problema que não estou encontrando solução (na verdade nem o problema, rsrs).

O caso é assim, tenho uma classe principal Palavra e suas subclasses, como Verbo, Artigo, Substantivo, etc.

Leio as palavras de um arquivo e tento persistir em um banco de dados (Postgres).
Para isso estou utilizando o hibernate, com a estratégia @Inheritance(strategy = InheritanceType.SINGLE_TABLE) na classe principal (Palavra), pois desejo que seja criada uma unica tabela no banco chamada palavra e conforme forem “surgindo” os tipos de palavra no arquivo ir acrescentando as colunas necessárias para determinado tipo.

Estou criando Threads para tentar otimizar o trabalho, visto que o arquivo é muito grande. Dessa forma, cada Thread é responsável por um “tipo” (Verbo, Substantivo, Artigo, etc).

Porém quando vou rodar a aplicação ocorre uma exceção informando que não foi possível criar algumas colunas, ora provenientes de uma Thread ora de outra.

Por exemplo:

ERRO: coluna “tipoadjetivo” da relação “palavra” não existe

ERRO: coluna “genero” da relação “palavra” não existe

Porem há casos que essas colunas são criadas e aí ocorrem problema em outras, ou até mesmo ocorre problemas em duas threads (mas o mais comum é apenas em uma).

Chamada das Threads:

	public static void main(String[] args) {


		new ThreadAdjetivos().start();
		new ThreadAdverbios().start();
		new ThreadArtigos().start();
		new ThreadConjuncoes().start();
		new ThreadGenericas().start();
		new ThreadInterjeicoes().start();
		new ThreadNumerais().start();
		new ThreadPreposicoes().start();
		new ThreadPronomes().start();
		new ThreadSubstantivos().start();
		new ThreadVerbos().start();

	}

Alguem saberia me dizer o que pode estar ocorrendo?

Obrigado.

[quote=jks1903]Pessoal, estou com um problema que não estou encontrando solução (na verdade nem o problema, rsrs).

O caso é assim, tenho uma classe principal Palavra e suas subclasses, como Verbo, Artigo, Substantivo, etc.

Leio as palavras de um arquivo e tento persistir em um banco de dados (Postgres).
Para isso estou utilizando o hibernate, com a estratégia @Inheritance(strategy = InheritanceType.SINGLE_TABLE) na classe principal (Palavra), pois desejo que seja criada uma unica tabela no banco chamada palavra e conforme forem “surgindo” os tipos de palavra no arquivo ir acrescentando as colunas necessárias para determinado tipo.

Estou criando Threads para tentar otimizar o trabalho, visto que o arquivo é muito grande. Dessa forma, cada Thread é responsável por um “tipo” (Verbo, Substantivo, Artigo, etc).

Porém quando vou rodar a aplicação ocorre uma exceção informando que não foi possível criar algumas colunas, ora provenientes de uma Thread ora de outra.

Por exemplo:

ERRO: coluna “tipoadjetivo” da relação “palavra” não existe

ERRO: coluna “genero” da relação “palavra” não existe

Porem há casos que essas colunas são criadas e aí ocorrem problema em outras, ou até mesmo ocorre problemas em duas threads (mas o mais comum é apenas em uma).

Chamada das Threads:

	public static void main(String[] args) {


		new ThreadAdjetivos().start();
		new ThreadAdverbios().start();
		new ThreadArtigos().start();
		new ThreadConjuncoes().start();
		new ThreadGenericas().start();
		new ThreadInterjeicoes().start();
		new ThreadNumerais().start();
		new ThreadPreposicoes().start();
		new ThreadPronomes().start();
		new ThreadSubstantivos().start();
		new ThreadVerbos().start();

	}

Alguem saberia me dizer o que pode estar ocorrendo?

Obrigado.
[/quote]

jks1903, pode colar a classe entidade Palavra?

Claro.

package modelo;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;

@SuppressWarnings("serial")
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "tipoPalavra", length = 3, discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue("PVR")
// palavra
public abstract class Palavra implements Serializable {
	@Id
	@GeneratedValue
	protected long idPalavra;
	protected String dsPalavra;
	protected String stringDicionario;
	@Column(insertable = false, updatable = false)
	protected String tipoPalavra;

	public String getDsPalavra() {
		return dsPalavra;
	}

	public String getTipoPalavra() {
		return tipoPalavra;
	}

	/**
	 * @param dsPalavra
	 * @param stringDicionario
	 */
	public Palavra(String dsPalavra, String stringDicionario) {
		this.dsPalavra = dsPalavra;
		this.stringDicionario = stringDicionario;
	}

	public String getStringDicionario() {
		return stringDicionario;
	}

	/**
	 * @param dsPalavra
	 */
	public Palavra(String dsPalavra) {
		this.dsPalavra = dsPalavra;
	}

}

[quote=jks1903]Claro.

[code]
package modelo;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;

[…]
[/code][/quote]

Obrigado jks1903.
Você está implementando desse jeito por preferência sua ou deve ser desenvolvida desse jeito?

Algum tempo eu tive que resolver algo parecido, acabei pesquisando algumas soluções e a melhor que encontrei foi utilizar strategy = InheritanceType.JOINED.
Qual a vantagem de trabalhar com essa estratégia? Será criado em seu banco uma tabela principal e tabelas filhas. Na tabela principal será armazenado tudo que tem dentro da entidade Palavra e nas tabelas filhas serão adicionados
as colunas (atributos) especializadas. O que vai conectar a tabela pai com as tabelas filhas é a chave primária. Ficaria algo mais ou menos assim:

Classe pai:

@Entity
@Table(name = "palavra")
@Inheritance(strategy = InheritanceType.JOINED)
public class Palavra implements Serializable
{
    @Id
    @Column(name = "codigo", nullable = false)
    private int codigo;

   // atributos

  // get's e set's
}

Classe filha número 1:

@Entity
@Table(name = "verbo")
public class Verbo extends Palavra
{
   // atributos especificos da classe filha

  // get's e set's
}

Classe filha número 2:

@Entity
@Table(name = "substantivo")
public class Substantivo extends Palavra
{
   // atributos especificos da classe filha

  // get's e set's
}

No banco, vai criar três tabelas assim:

palavra: codigo, colunas correspondentes aos atributos dessa classe
verbo: codigo, colunas correspondentes aos atributos dessa classe
substantivo: codigo, colunas correspondentes aos atributos dessa classe

Daí por exemplo, se você inserir um registro na tabela verbo, automaticamente é inserido um registro na tabela palavra. O que vai dizer a relação dos registros nas duas tabelas é o código que será o mesmo para as duas.

Deu para entender mais ou menos?

Estou desenvolvendo dessa forma por opção mesmo.

Mas tinha escolhido essa estratégia devido a minha necessidade posterior.

Precisarei analisar textos e semântica. Aí tenho que saber o que a palavra “abacaxi” é, ou seja, se é verbo, adjetivo, substantivo, etc.
Tendo tudo em uma única tabela acho mais fácil essa atividade depois.

Mas fazendo da forma como estou fazendo estaria errado, para estar gerando esse problema?

Obrigado pelas respostas.

[quote=jks1903]Estou desenvolvendo dessa forma por opção mesmo.

Mas tinha escolhido essa estratégia devido a minha necessidade posterior.

Precisarei analisar textos e semântica. Aí tenho que saber o que a palavra “abacaxi” é, ou seja, se é verbo, adjetivo, substantivo, etc.
Tendo tudo em uma única tabela acho mais fácil essa atividade depois.

Mas fazendo da forma como estou fazendo estaria errado, para estar gerando esse problema?

Obrigado pelas respostas.[/quote]

Por nada jks1903.
Não que esteja errado, mas no meu caso desse jeito que te mostrei foi mais apropriado.
Pode colar as classes filhas?

No caso são várias classes, todas seguem a mesma estrutura praticamente.

Vou postar algumas, que já dá pra se basear:

Classe Substantivo:

package modelo;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@SuppressWarnings("serial")
@Entity
@DiscriminatorValue(value = "SUB")
public class Substantivo extends Palavra {
	private String genero;
	private char singPlural;

	public String getGenero() {
		return genero;
	}

	public char getSingPlural() {
		return singPlural;
	}

	/**
	 * @param dsPalavra
	 * @param stringDicionario
	 * @param genero
	 * @param singPlural
	 */
	public Substantivo(String dsPalavra, String stringDicionario,
			String genero, char singPlural) {
		super(dsPalavra, stringDicionario);
		this.genero = genero;
		this.singPlural = singPlural;
	}







}

Classe Pronome

package modelo;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@SuppressWarnings("serial")
@Entity
@DiscriminatorValue(value = "PRO")
public class Pronome extends Palavra {
	private String tipoPronome;

	public String getTipoPronome() {
		return tipoPronome;
	}

	/**
	 * @param dsPalavra
	 * @param stringDicionario
	 * @param tipoPronome
	 */
	public Pronome(String dsPalavra, String stringDicionario, String tipoPronome) {
		super(dsPalavra, stringDicionario);
		this.tipoPronome = tipoPronome;
	}





	
	
	
}

Classe Artigo

package modelo;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@SuppressWarnings("serial")
@Entity
@DiscriminatorValue(value = "ART")
public class Artigo extends Palavra {
	private String tipoArtigo;

	public String getTipoArtigo() {
		return tipoArtigo;
	}

	/**
	 * @param dsPalavra
	 * @param stringDicionario
	 * @param tipoArtigo
	 */
	public Artigo(String dsPalavra, String stringDicionario, String tipoArtigo) {
		super(dsPalavra, stringDicionario);
		this.tipoArtigo = tipoArtigo;
	}





}

Todas seguem estrutura semelhante, o que difere mesmo é o atributo especifico, como tipoPronome, tipoArtigo, etc. Verifiquei os atributos e nenhum atributo tem nome em comum entre as classes filhas.

Assim, pelo que vi as anotações estão corretas. Só tem alguns detalhes que você teria que arrumar, não querendo ser chato, mas até mesmo para boas práticas com programação Java. Eu vou listar aqui elas:

  • Organize suas classes assim: atributos, construtores e métodos get’s e set’s;
  • Quando você criar um novo construtor, sempre coloque o construtor padrão, que é limpo sem nenhum atributo;
  • Não que seja necessário, mas todos os atributos tem que ter um método get e um método set. Por exemplo
private int idade;

public void setIdade(int idade)
{
   this.idade = idade;
}

public int getIdade()
{
  return idade;
}
  • Eu arrumei a sua classe pai (palavra) e uma de suas classes filhas. Tente arrumar nesse padrão, pode ser que tenha passado algo despercebido.

Classe Palavra

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "tipoPalavra", length = 3, discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue("PVR")
public abstract class Palavra implements Serializable
{
  // atributos
  @Id
  @GeneratedValue
  protected long idPalavra;
  
  protected String dsPalavra;
  
  protected String stringDicionario;
  
  @Column(insertable = false, updatable = false)
  protected String tipoPalavra;

  // construtores
  public Palavra(){}
  
  public Palavra(String dsPalavra)
  {
    this.dsPalavra = dsPalavra;
  }

  public Palavra(String dsPalavra, String stringDicionario)
  {
    this.dsPalavra = dsPalavra;
    this.stringDicionario = stringDicionario;
  }

  // get's e se'ts
  public long getIdPalavra()
  {
    return idPalavra;
  }

  public void setIdPalavra(long idPalavra)
  {
    this.idPalavra = idPalavra;
  }

  public String getDsPalavra()
  {
    return dsPalavra;
  }

  public void setDsPalavra(String dsPalavra)
  {
    this.dsPalavra = dsPalavra;
  }

  public String getStringDicionario()
  {
    return stringDicionario;
  }

  public void setStringDicionario(String stringDicionario)
  {
    this.stringDicionario = stringDicionario;
  }

  public String getTipoPalavra()
  {
    return tipoPalavra;
  }

  public void setTipoPalavra(String tipoPalavra)
  {
    this.tipoPalavra = tipoPalavra;
  }
}

Classe Substantivo

@Entity
@DiscriminatorValue(value = "SUB")
public class Substantivo extends Palavra
{
  // atributos
  private String genero;
  
  private char singPlural;



  // construtores
  public Substantivo(){} // contrutor padrão
  
  public Substantivo(String dsPalavra, String stringDicionario,String genero, char singPlural)
  {
    super(dsPalavra, stringDicionario);
    this.genero = genero;
    this.singPlural = singPlural;
  }
  
  // get's e set's
  public String getGenero()
  {
    return genero;
  }

  public void setGenero(String genero)
  {
    this.genero = genero;
  }

  public char getSingPlural()
  {
    return singPlural;
  }

  public void setSingPlural(char singPlural)
  {
    this.singPlural = singPlural;
  }
}

vou ajustar a ordem correta mesmo, atributos, contstrutores e metodos.

Porém referente aos construtores, não posso criar um construtor “vazio” porque desejo que seja obrigatório a informação desses valores a cada nova instância dessa classe.

Como utilizo sempre esse construtor, não há necessidade de criar os sets, por isso existem apenas os gets.

MAs referente ao problema que citei na abertura do tópico, eu não utilizo muito hibernate, então encontrei um tutorial que tinha e configurei o mesmo utilizando os arquivos properties ao invés de XMLs. Com isso, utilizei AnnotationConfiguration, e vi que o eclipse sinalizou alguns métodos como deprecated. Pode ter alguma relação a isso?

De qualquer forma vou procurar uma documentação apresentando como realizar a configuração com XML e tentar novamente.

Obrigado.

[quote=jks1903]vou ajustar a ordem correta mesmo, atributos, contstrutores e metodos.

Porém referente aos construtores, não posso criar um construtor “vazio” porque desejo que seja obrigatório a informação desses valores a cada nova instância dessa classe.

Como utilizo sempre esse construtor, não há necessidade de criar os sets, por isso existem apenas os gets.

MAs referente ao problema que citei na abertura do tópico, eu não utilizo muito hibernate, então encontrei um tutorial que tinha e configurei o mesmo utilizando os arquivos properties ao invés de XMLs. Com isso, utilizei AnnotationConfiguration, e vi que o eclipse sinalizou alguns métodos como deprecated. Pode ter alguma relação a isso?

De qualquer forma vou procurar uma documentação apresentando como realizar a configuração com XML e tentar novamente.

Obrigado.[/quote]

Tranquilo jks1903.
Pra te falar a verdade, tive alguns problemas com frameworks porque criei um novo construtor e não defini o padrão.
Acredito que o framework utilizava o construtor padrão para trabalhar com as classes anotadas.
Se puder colar aqui o seu XML, eu comparo com o meu e te digo se tem alguma diferença.

Outra coisa, ao invés de deixar sem get ou set, define eles como sendo private.

Abraço

Consegui solucionar o problema.

O que ocorria, acredito eu, é que como eu estava trabalhando com Threads, alguma Thread não conseguia criar alguma coluna devido à tabela estar sendo alterada no momento, com um insert por exemplo.

O que fiz então foi efetuar um SchemaExport antes de iniciar a persistência, dessa forma todas as colunas necessárias já teriam sido criadas antes da inserção de qualquer dado.

Feito isso, o problema foi resolvido.

Obrigado.