Spring, Hibernate et projections
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:
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:
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:
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