Reputation: 419
I use Hibernate 3.5.6 and MySQL 5.1. I have 3 classes: Item, Attribute, AttributeValue. They relate to each other with a One-to-Many relationship, and I do get all Attributes for a given Item. But I don't get AttributeValues for a given Attribute. I cannot see exceptions or errors, and data in the tables looks good, meaning that insertion of the data went well.
I have tried different strategies for FetchMode of Attribute's map of AttributeValues, but result is always empty.
What have I missed?
Here are the classes:
@Entity
@Table(name = "Item")
public class Item implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String serialNumber;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "item", cascade = CascadeType.ALL)
@Fetch(value = FetchMode.SELECT) // don't remove this line
@MapKey(name = "name")
private Map<String, Attribute> attributes = new HashMap<String, Attribute>();
protected Item() {
super();
}
public Item(String serialNumber) {
this();
setSerialNumber(serialNumber);
}
public String getSerialNumber() {
return serialNumber;
}
protected void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
public Map<String, Attribute> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, Attribute> attributes) {
this.attributes = attributes;
}
}
@Entity
@Table(name = "Attribute", uniqueConstraints = {@UniqueConstraint(columnNames = {"item_serialNumber", "name"})})
public class Attribute implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne(cascade = CascadeType.ALL)
private Item item;
@Column(nullable = false)
private String name;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "value", cascade = CascadeType.ALL)
@Fetch(value = FetchMode.SELECT)
@MapKey(name = "value")
private Map<String, AttributeValue> values = new HashMap<String, AttributeValue>();
protected Attribute() {
super();
}
public Attribute(String name) {
super();
this.name = name;
}
public Integer getId() {
return id;
}
protected void setId(Integer id) {
this.id = id;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public String getName() {
return name;
}
protected void setName(String newName) {
this.name = newName;
}
public Map<String, AttributeValue> getValues() {
return values;
}
public void setValues(Map<String, AttributeValue> values) {
this.values = values;
}
}
@Entity
@Table(name = "AttributeValue", uniqueConstraints = {@UniqueConstraint(columnNames = {"attribute_id", "value"})})
public class AttributeValue implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column
private String value;
@ManyToOne(cascade = CascadeType.ALL)
private Attribute attribute;
protected AttributeValue() {
super();
}
public AttributeValue(String value) {
this.value = value;
}
protected Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getValue() {
return value;
}
/**
* @param value the value to set
*/
protected void setValue(String value) {
this.value = value;
}
/**
* @return the attribute
*/
public Attribute getAttribute() {
return attribute;
}
/**
* @param attribute the attribute to set
*/
public void setAttribute(Attribute attribute) {
this.attribute = attribute;
}
}
And here is the SQL of the underlying tables:
--
-- Table structure for table `Attribute`
--
CREATE TABLE `Attribute` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`item_serialNumber` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `item_serialNumber` (`item_serialNumber`,`name`),
KEY `FK7839CA7C252F491C` (`item_serialNumber`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `Item`
--
CREATE TABLE `Item` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`serialNumber` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `serialNumber` (`serialNumber`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `AttributeValue`
--
CREATE TABLE `AttributeValue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`value` varchar(255) DEFAULT NULL,
`attribute_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `attribute_id` (`attribute_id`,`value`),
KEY `FK4C1BA6C69CA0A39A` (`attribute_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `Attribute`
--
ALTER TABLE `Attribute`
ADD CONSTRAINT `FK7839CA7C252F491C` FOREIGN KEY (`item_serialNumber`) REFERENCES `Item` (`serialNumber`);
--
-- Constraints for table `AttributeValue`
--
ALTER TABLE `AttributeValue`
ADD CONSTRAINT `FK4C1BA6C69CA0A39A` FOREIGN KEY (`attribute_id`) REFERENCES `Attribute` (`id`);
Upvotes: 9
Views: 21493
Reputation: 2071
You have mapped the values
map in Attribute using 'value' instead of 'attribute'.
The @OneToMany annotation should be specified as below:
@OneToMany(fetch = FetchType.EAGER, mappedBy = "attribute", cascade = CascadeType.ALL)
Upvotes: 6