Relação @One-to-Many sem primary key

Olá terráqueos,

Existe a possibilidade de fazer uma relação @One-to-Many sem Primary Key na tabela filha?

Segue minhas duas entidades
Entidade NOTICIA:

@Entity
@Table(name = "NOTICIA")
@NamedQueries({
    @NamedQuery(name = "Noticia.findAll", query = "SELECT n FROM Noticia n"),
    @NamedQuery(name = "Noticia.findAllByDate", query = "SELECT n FROM Noticia n WHERE n.dhCadastro BETWEEN :startDate AND :endDate")
})
public class Noticia implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    //@GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "cdNoticia")
    private Long cdNoticia;

    @Basic(optional = false)
    @Column(name = "cdVeiculo")
    private long cdVeiculo;
    @Column(name = "nmAutor")
    private String nmAutor;
    @Column(name = "cdColunista")
    private Short cdColunista;
    @Basic(optional = false)
    @Column(name = "cdSecao")
    private short cdSecao;
    @Column(name = "dsTitulo")
    private String dsTitulo;
    @Lob
    @Column(name = "dsTexto")
    private String dsTexto;
    @Basic(optional = false)
    @Column(name = "dsURL")
    private String dsURL;
    @Column(name = "cdHash")
    private String cdHash;
    @Basic(optional = false)
    @Column(name = "dtNoticia")
    @Temporal(TemporalType.DATE)
    private Date dtNoticia;
    @Basic(optional = false)
    @Column(name = "hrNoticia")
    @Temporal(TemporalType.TIME)
    private Date hrNoticia;
    @Column(name = "dhCadastro")
    @Temporal(TemporalType.TIMESTAMP)
    private Date dhCadastro;
    @Basic(optional = false)
    @Column(name = "idTipo")
    private String idTipo;
    @Basic(optional = false)
    @Column(name = "idDigitalizada")
    private String idDigitalizada;

    @Column(name = "isTransicao")
    private Integer isTransicao;

    @Column(name = "isElasticSearch")
    private Integer isElasticSearch;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "noticia", orphanRemoval = true)
    private List<Noticiaimagem> noticiaimagemCollection = new ArrayList<Noticiaimagem>();



    public Noticia() {
    }

    public Long getCdNoticia() {
        return cdNoticia;
    }

    public void setCdNoticia(Long cdNoticia) {
        this.cdNoticia = cdNoticia;
    }

    public long getCdVeiculo() {
        return cdVeiculo;
    }

    public void setCdVeiculo(long cdVeiculo) {
        this.cdVeiculo = cdVeiculo;
    }

    public String getNmAutor() {
        return nmAutor;
    }

    public void setNmAutor(String nmAutor) {
        this.nmAutor = nmAutor;
    }

    public Short getCdColunista() {
        return cdColunista;
    }

    public void setCdColunista(Short cdColunista) {
        this.cdColunista = cdColunista;
    }

    public short getCdSecao() {
        return cdSecao;
    }

    public void setCdSecao(short cdSecao) {
        this.cdSecao = cdSecao;
    }

    public String getDsTitulo() {
        return dsTitulo;
    }

    public void setDsTitulo(String dsTitulo) {
        this.dsTitulo = dsTitulo;
    }

    public String getDsTexto() {
        return dsTexto;
    }

    public void setDsTexto(String dsTexto) {
        this.dsTexto = dsTexto;
    }

    public String getDsURL() {
        return dsURL;
    }

    public void setDsURL(String dsURL) {
        this.dsURL = dsURL;
    }

    public String getCdHash() {
        return cdHash;
    }

    public void setCdHash(String cdHash) {
        this.cdHash = cdHash;
    }

    public Date getDtNoticia() {
        return dtNoticia;
    }

    public void setDtNoticia(Date dtNoticia) {
        this.dtNoticia = dtNoticia;
    }

    public Date getHrNoticia() {
        return hrNoticia;
    }

    public void setHrNoticia(Date hrNoticia) {
        this.hrNoticia = hrNoticia;
    }

    public Date getDhCadastro() {
        return dhCadastro;
    }

    public void setDhCadastro(Date dhCadastro) {
        this.dhCadastro = dhCadastro;
    }

    public String getIdTipo() {
        return idTipo;
    }

    public void setIdTipo(String idTipo) {
        this.idTipo = idTipo;
    }

    public String getIdDigitalizada() {
        return idDigitalizada;
    }

    public void setIdDigitalizada(String idDigitalizada) {
        this.idDigitalizada = idDigitalizada;
    }

    public Integer getIsTransicao() {
        return isTransicao;
    }

    public void setIsTransicao(Integer isTransicao) {
        this.isTransicao = isTransicao;
    }

    public Integer getIsElasticSearch() {
        return isElasticSearch;
    }

    public void setIsElasticSearch(Integer isElasticSearch) {
        this.isElasticSearch = isElasticSearch;
    }

    public List<Noticiaimagem> getNoticiaimagemCollection() {
        return noticiaimagemCollection;
    }

    public void setNoticiaimagemCollection(List<Noticiaimagem> noticiaimagemCollection) {
        this.noticiaimagemCollection = noticiaimagemCollection;
    }
} 

Entidade NOTICIAIMAGEM:

@Entity
@Table(name = "NOTICIAIMAGEM")
public class Noticiaimagem implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @ManyToOne
    @JoinColumn(name = "cdNoticia", nullable = false)
    @MapsId
    private Noticia noticia;

    @Column
    private String nmImagem;

    @Column(nullable = false)
    private String nmExtensao;

    @Column
    private Float nrTamanho;
    @Column(columnDefinition = "UNSIGNED SMALLINT(5)")
    private Integer nrAltura;
    @Column(columnDefinition = "UNSIGNED SMALLINT(5)")
    private Integer nrLargura;
    @Column(columnDefinition = "UNSIGNED TINYINT(3)")
    private Integer nrOrdem;
    @Column(columnDefinition = "UNSIGNED MEDIUMINT(8)")
    private Integer cdTipoNoticiaImagem;

    public Noticiaimagem() {
    }

    public Noticia getNoticia() {
        return noticia;
    }

    public void setNoticia(Noticia noticia) {
        this.noticia = noticia;
    }

    public String getNmImagem() {
        return nmImagem;
    }

    public void setNmImagem(String nmImagem) {
        this.nmImagem = nmImagem;
    }

    public String getNmExtensao() {
        return nmExtensao;
    }

    public void setNmExtensao(String nmExtensao) {
        this.nmExtensao = nmExtensao;
    }

    public Float getNrTamanho() {
        return nrTamanho;
    }

    public void setNrTamanho(Float nrTamanho) {
        this.nrTamanho = nrTamanho;
    }

    public Integer getNrAltura() {
        return nrAltura;
    }

    public void setNrAltura(Integer nrAltura) {
        this.nrAltura = nrAltura;
    }

    public Integer getNrLargura() {
        return nrLargura;
    }

    public void setNrLargura(Integer nrLargura) {
        this.nrLargura = nrLargura;
    }

    public Integer getNrOrdem() {
        return nrOrdem;
    }

    public void setNrOrdem(Integer nrOrdem) {
        this.nrOrdem = nrOrdem;
    }

    public Integer getCdTipoNoticiaImagem() {
        return cdTipoNoticiaImagem;
    }

    public void setCdTipoNoticiaImagem(Integer cdTipoNoticiaImagem) {
        this.cdTipoNoticiaImagem = cdTipoNoticiaImagem;
    }
}

As regras de banco de dados, são refletidas no ORM, ou seja, todas as relações precisam existir, na minha visão é uma falha grave não existir a chave primária e a chave estrangeira em relacionamentos de tabelas, sendo usado pelo ORM de forma transparente!

1 curtida

Concordo com você, porém, o sistema é legado. A tabela possui mais de 6 milhões de registros… Seria inviável alterar a tabela nessa altura do campeonato.
Fiz um teste criando outro banco e adicionei a primary key na tabela NOTICIAIMAGEM, depois fiz a alteração na Entidade. Obtive sucesso na inserção. Agora se eu tentar sem a primary key, a aplicação não insere o registro e também não retorna nem uma exception…

Então, o problema continua, não tem solução com ORM, faça uma camada auxiliar com JDBC, é a solução viável

Sou iniciante em Java. Eu estou aprendendo a trabalhar com o ORM do hibernate.

Andei pesquisando e achei uma annotation @Formula que é usado para fazer consultas em tabelas que não possuem relação. Por acaso, ela se encaixaria no meu contexto ?

Sinceramente não sei, precisa que alguém lhe diga não sou experiente com Nhibernate ( eu sei a forma padrão, mas, ele tem inúmeras configurações )

Qual relação existem entre as tabelas:

Tem como colar um imagem da relação?

A relação é 1 NOTICIA para N NOTICIAIMAGEM. São associadas pelo cdNoticia, porém, não existe foreing key.

Se eu não me engano, as camadas ORM, tem uma regra de que todas as entidades devem possuir uma chave primaria, pelo menos as que eu mexo são assim, uma vez trabalhei com FluentNhibernate e ele também só aceita adicionar entidades com chave primária.

Pelo ORM não vai ser gerado a entidade, é uma das regra do Framework de Persistência, e perceba que no desenho não tem a linha que liga as duas tabelas, ou seja, são independentes (tem relação que nós programadores sabemos, mas, o banco não.).

Tudo que for feito dentro do ORM eu vejo como "gambiarra", como é um banco legado, ratifico, utilize um JDBC somente para essa entidade. Com JDBC você terá o controle dela e você resgata a chave para gravar.!

Um pergunta que não quer calar:

####Como você exclui imagem dessa tabela, já visto que tem um erro de design e não possui um indentificador de linha (primary key), já pensou nisso?

####Será que não seria bom colocar uma chave primary e um chave estrangeira nessa tabela, faça um backup desse banco e tente, seria uma forma de resolver, não seria?