Bonjour,
débutant avec Hibernate, à partir d'une base de donnée, j'ai testé le Reverse Engineering d'Hibernate sous Eclipse pour voir si le code que j'obtenais ressemblais à celui qui m'a permit de créer la base.
Je suis parti de cette simple base :
Et j'ai obtenu ce code (getter et setter laissé de coté) :
Classe A :
Code:
@Entity
@Table( name = "TABLE_A")
public class A implements Serializable
{
/** Auto generated id of the table. */
@Id
@SequenceGenerator( name = "SEQ_ID_A_GEN", sequenceName = "SEQ_ID_A", initialValue = 1, allocationSize = 1 )
@GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "SEQ_ID_A_GEN" )
@Column( name = "ID_A", nullable = false )
private Integer idA;
/** */
@Column( name = "NAME_A")
private String name;
/** */
@OneToMany( cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "objectA" )
private List<B> listOfB = new ArrayList<B>();
/**
* Constructor without parameters.
*/
public A()
{
}
...
}
Classe B :
Code:
@Entity
@Table( name = "TABLE_B" )
public class B implements Serializable
{
/** Multiple Identity for this table. */
@EmbeddedId
@AttributeOverrides( {
@AttributeOverride( name = "idA", column = @Column( name = "ID_A", nullable = false ) ),
@AttributeOverride( name = "idB", column = @Column( name = "ID_B", nullable = false ) ) } )
private BPrimaryKey pkB = new BPrimaryKey();
/** */
@ManyToOne( fetch = FetchType.LAZY )
@JoinColumn( name = "ID_A", nullable = false, insertable = false, updatable = false )
private A objectA;
/** */
@Column( name = "NAME_B" )
private String name;
/**
* Constructor without parameters.
*/
public B()
{
}
...
@Embeddable
public static class BPrimaryKey implements Serializable
{
/** */
@Column( name = "ID_A", nullable = false )
private Integer idA;
/** Number of the sequence. */
@Column( name = "ID_B" )
private Integer idB;
/**
* Constructor without parameters.
*/
public BPrimaryKey()
{
}
...
Code de test :
Code:
public class TestBase
{
private static EntityManager em;
private static EntityManagerFactory emf;
@BeforeClass
public static void setUpBeforeClass() throws Exception
{
emf = Persistence.createEntityManagerFactory( "sample" );
}
@AfterClass
public static void tearDownAfterClass() throws Exception
{
emf.close();
}
@Before
public void setUp() throws Exception
{
em = emf.createEntityManager();
}
@After
public void tearDown() throws Exception
{
em.close();
}
@Test
public void testRemplissage()
{
EntityTransaction tx = em.getTransaction();
tx.begin();
A objA = new A();
objA.setName("New Object A");
em.persist( objA );
B objB = new B();
objB.setName( "New Object B" );
objB.setObjectA( objA );
//objB.getPkB().setIdA( objA.getIdA() );
objB.getPkB().setIdB( 1 );
objA.getListOfB().add( objB );
em.persist( objB );
tx.commit();
}
}
Ce code de test me provoque une exception indiquant que on ne peut pas inserer NULL dans ID_A de la table B.
En effet je suis obligé de décommenter la ligne
Code:
//objB.getPkB().setIdA( objA.getIdA() );
Pour que l'identificateur ne soit pas null et là ca marche.
Or mon code à la base ressemblait à ca (fait à partir des exemples trouvé sur le net)
Classe A :
Code:
@Entity
@Table( name = "TABLE_A")
public class A implements Serializable
{
/** Auto generated id of the table. */
@Id
@SequenceGenerator( name = "SEQ_ID_A_GEN", sequenceName = "SEQ_ID_A", initialValue = 1, allocationSize = 1 )
@GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "SEQ_ID_A_GEN" )
@Column( name = "ID_A", nullable = false )
private Integer idA;
/** */
@Column( name = "NAME_A")
private String name;
/** */
@OneToMany( cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "pkB.objectA" )
private List<B> listOfB = new ArrayList<B>();
/**
* Constructor without parameters.
*/
public A()
{
}
Classe B :
Code:
@Entity
@Table( name = "TABLE_B" )
@AssociationOverrides( { @AssociationOverride( name = "pkB.objectA", joinColumns = @JoinColumn( name = "ID_A" ) ) } )
public class B implements Serializable
{
/** Multiple Identity for this table. */
@EmbeddedId
private BPrimaryKey pkB = new BPrimaryKey();
/** */
@Column( name = "NAME_B" )
private String name;
/**
* Constructor without parameters.
*/
public B()
{
}
...
@Embeddable
public static class BPrimaryKey implements Serializable
{
/** */
@ManyToOne( fetch = FetchType.LAZY )
private A objectA;
/** Number of the sequence. */
@Column( name = "ID_B" )
private Integer idB;
/**
* Constructor without parameters.
*/
public BPrimaryKey()
{
}
}
Par ce moyen, Hibernate récupère, comme un grand, l'identificateur de la classe mère sans avoir besoin de lui passer.
J'aimerai juste comprendre comment faire fonctionner le code généré par Hibernate pour qu'il aille chercher l'identifiant ID_A dans l'objet mission et non pas en lui donnant explicitement dans le code de test.
Est-il préférable de faire comme j'ai fait ? en mettant l'objet parent directement dans la classe Embeddable ou vaut-il mieux faire comme hibernate le génère. Merci.
PS : Sources des deux projets eclipse téléchargeable a cette adresse :
http://dl.free.fr/lAVw0jh4V