Hibernate version: 3.2.5.ga
Hibernate Annotations version: 3.3.0.ga
MySql 5 / PostgreSQL 8.1
Many times I tried using Hibernate for my small projects, but I always gave up at the first collection mapping problem.
Now I can afford some debug time, so I put together a small example demonstrating my
newbie problems.
I would like to express a OneToMany bidirectional (or even unidirectional) association with a Map<>, and to save new objects to the database with matching IDs. My example is a User entity with multiple Address related entities. The Map's key is an AddressType column.
What I'd like to obtain is to be able to create a new user, with one or more addresses, and to save it with as little iterations as possible with the back-end.
I tried all the permutations I could imagine, and neither worked, so as a last resort I thought I'd ask for some help here.
Can someone point me in the right direction?
Thanks,
Angelo.
This is the main code (all the juicy part is in the doWork() function):
Code:
package test;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
public class Test {
/**
* @param s the Hibernate session to work on
*/
private static void doWork(Session s) {
User user = new User("John","blah");
Address addr = new Address();
addr.setStreetAddr("Prova Indirizzo");
user.setAddr(addr, 0);
s.save(user);
System.out.println("saved "+user.getId());
s.save(addr);
}
/**
* @param args ignored
*/
public static void main(String[] args) {
//boilerplate connection setup
AnnotationConfiguration config = new AnnotationConfiguration();
config.addAnnotatedClass(User.class)
.addAnnotatedClass(Address.class);
config.setProperty("hibernate.hbm2ddl.auto", "update");
SessionFactory sessionFactory = config.buildSessionFactory();
Session s = sessionFactory.openSession();
Transaction tx = s.beginTransaction();
doWork(s);
tx.commit();
s.close();
s = null;
}
}
and the properties file:
Code:
######################
### Query Language ###
######################
## define query language constants / function names
hibernate.query.substitutions true 1, false 0, yes 'Y', no 'N'
## select the classic query parser
#hibernate.query.factory_class org.hibernate.hql.classic.ClassicQueryTranslatorFactory
## MySQL
hibernate.dialect org.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class com.mysql.jdbc.Driver
hibernate.connection.url jdbc:mysql://localhost/prove
hibernate.connection.username prove
hibernate.connection.password prove
#################################
### Hibernate Connection Pool ###
#################################
hibernate.connection.pool_size 1
hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory
## print all generated SQL to the console
hibernate.show_sql true
hibernate.connection.isolation 8
hibernate.jdbc.batch_versioned_data true
hibernate.jdbc.use_streams_for_binary true
Here are the entities:
Code:
package test;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
@Entity
public class User {
Long id;
String name;
String username;
@OneToMany(mappedBy="userID",cascade=CascadeType.ALL)
@MapKey(name="addrType")
@JoinColumn(name="id",referencedColumnName="userId")
public Map<Integer,Address> address;
public User(){}
public User(String name, String username){
super();
this.name = name;
this.username = username;
}
@Id @GeneratedValue
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getUsername() {
return username;
}
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setUsername(String username) {
this.username = username;
}
public void setAddr(Address addr, int addrType) {
if (address==null) address = new HashMap<Integer, Address>();
addr.setAddrType(addrType);
addr.user = this;
address.put(addrType,addr);
}
}
Code:
package test;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
@Entity
public class Address {
Long userID;
Long myId;
Integer addrType;
String streetAddr;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="userID",referencedColumnName="id", nullable=false, updatable=false)
public User user;
public Long getUserID() {
return userID;
}
public void setUserID(Long userID) {
this.userID = userID;
}
public Integer getAddrType() {
return addrType;
}
public void setAddrType(Integer addrType) {
this.addrType = addrType;
}
public String getStreetAddr() {
return streetAddr;
}
public void setStreetAddr(String streetAddr) {
this.streetAddr = streetAddr;
}
@Id @GeneratedValue
public Long getMyId() {
return myId;
}
public void setMyId(Long myId) {
this.myId = myId;
}
}