Bonjour,

Je rencontre un problème de mapping objet/relationnel sur une appli Spring+Hibernate+Mysql. L'archi globale est la suivante:

Couche métier (Spring) --> couche DAO (Spring+Hibernate) --> Beans model (transverse à toute l'application)

Ma gestion de hibernate est entièrement déléguée à Spring et j'utilise des annotations pour mes entités.

Voici le code de mon entité:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 
@Entity
@Table(name = "product", catalog = "my_catalog", uniqueConstraints = @UniqueConstraint(columnNames = "generic_name"))
public class Product implements Serializable {
 
	private static final long serialVersionUID = -1881936584394110049L;
 
	private Integer id;
	private String genericName;
        private Set<ProductAvailability> productAvailabilities = new HashSet<ProductAvailability>(0);
 
        @Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "id", unique = true, nullable = false)
	public Integer getId() {
		return this.id;
	}
 
	public void setId(Integer id) {
		this.id = id;
	}
 
        @Column(name = "generic_name", unique = true, nullable = false, length = 25)
	public String getGenericName() {
		return this.genericName;
	}
 
	public void setGenericName(String genericName) {
		this.genericName = genericName;
	}
 
        @OneToMany(fetch = FetchType.EAGER, mappedBy = "product")
	public Set<ProductAvailability> getProductAvailabilities() {
		return this.productAvailabilities;
	}
 
	public void setProductAvailabilities(
			Set<ProductAvailability> productAvailabilities) {
		this.productAvailabilities = productAvailabilities;
	}
}
 
@Entity
@Table(name = "product_availability", catalog = "my_catalog")
public class ProductAvailability implements java.io.Serializable {
 
	private static final long serialVersionUID = -2133958619360018974L;
 
	private ProductAvailabilityId id;
	private ProductSize productSize;
	private Product product;
 
        //getters and setters ...
}
 
@Embeddable
public class ProductAvailabilityId implements java.io.Serializable {
 
	private static final long serialVersionUID = -6106195773528063342L;
 
	private int refProduct;
	private int refSize;
	private int quantity;
	private String reference;
 
        //getters and setters ...
}
Voici le code de mon Dao:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao {
 
       public Product getProductDetailByName(String name, String languageCode) {
		try {
			Session session = getHibernateTemplate().getSessionFactory().getCurrentSession();
			Criteria crit = session.createCriteria(Product.class);
			crit.add(Expression.eq("genericName", name));	crit.setProjection(getLocalizedProductDetailByNameProjection(languageCode));			crit.setResultTransformer(Transformers.aliasToBean(Product.class));
 
			Product product = (Product) crit.uniqueResult();
			return product;
		} catch (DataAccessException e) {
                     //error treatment
                }
	}
 
        private ProjectionList getLocalizedProductDetailByNameProjection(
			String languageCode) {
		ProjectionList currentList = Projections.projectionList();
		currentList.add(Projections.property("id"), "id");
	     currentList.add(Projections.property("genericName"), "genericName");
        }
}
Et finalement le code sql de creation de bd:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
CREATE TABLE product_size(
    id INTEGER NOT NULL PRIMARY KEY auto_increment,
    name VARCHAR(15) NOT NULL,
    short VARCHAR(3) NOT NULL,
    UNIQUE (name, short)
)TYPE=INNODB DEFAULT CHARSET=utf8;
 
CREATE TABLE product(
    id INTEGER NOT NULL PRIMARY KEY auto_increment,
    generic_name VARCHAR(25) NOT NULL UNIQUE,
)TYPE=INNODB DEFAULT CHARSET=utf8;
 
CREATE TABLE product_availability(
		ref_product INTEGER NOT NULL,
		ref_size INTEGER NOT NULL,
		quantity INTEGER NOT NULL,
    	reference VARCHAR(25) NOT NULL,
    FOREIGN KEY (ref_product) REFERENCES product(id) ON DELETE CASCADE,
    FOREIGN KEY (ref_size) REFERENCES product_size(id) ON DELETE CASCADE
)TYPE=INNODB DEFAULT CHARSET=utf8;
Mon problème maintenant: Quand j'exécute ProductDaoImpl.getProductDetailByName(...) il me rempli bien tous les champs sauf la collection alors que le FetchType est en EAGER.
Pire encore, lorsque je comment les lignes
crit.setProjection(getLocalizedProductDetailByNameProjection(languageCode)); crit.setResultTransformer(Transformers.aliasToBean(Product.class));
la collection est bien remplie avec les objets de disponibilités de produits.

Donc, j'en arrive à la conclusion que c'est la projection qui pose problème, mais je ne vois pas où ...
J'ai essayé de jouer avec avec des instructions comme:
crit.setFetchMode("productAvailabilities", FetchMode.JOIN);
mais ça ne marche pas mieux ...

Quelqu'un aurait-il une idée pourquoi je ne peux pas combiner une projection avec une collection?

Merci d'avance