Reputation: 580
So, I'm making this webapp using Hibernate 5 and SpringMVC 4. I can't, for some reason, insert an entity with a OneToMany relation. Before I explain anything first I want to say that i tried many of the solutions posted here and other forums and neither worked for me... I don't know if I'm doing something wrong while trying to solve the issue.
Now, i recently added the phone table. Before this, I could add a profile object and it would cascade the inserts of the address and user entities on the same transaction. Now, with the addition of the phone entity to the code the persist operation keeps throwing me
Column 'ProfileId' cannot be null
All classes have their respective Setters and Getters... but to keep the code short, I removed them.
@Entity
@Table(name = "profile")
public class Profile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@NotEmpty
@Size(max = 100)
@Column(name = "FirstName", nullable = false, unique = false, length = 100)
private String firstName;
@NotEmpty
@Size(max = 100)
@Column(name = "LastName", nullable = false, unique = false, length = 100)
private String lastName;
@NotNull
@DateTimeFormat(pattern = "MM/dd/yyyy")
@Column(name = "BirthDate", nullable = false, unique = false)
private Timestamp birthDate;
@Valid
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "UserId")
private User user;
@Valid
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "AddressId")
private Address address;
@Valid
@OneToMany(fetch = FetchType.EAGER, mappedBy = "profile", cascade = CascadeType.ALL)
private List<Phone> phones;
}
_
@Entity
@Table(name = "Phone")
public class Phone {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@NotEmpty
@Size(max = 50)
@Column(name = "PhoneNumber", nullable = false, unique = false, length = 50)
private String phoneNumber;
@Valid
@ManyToOne(cascade = CascadeType.ALL, optional = false)
@JoinColumn(name = "ProfileId", nullable = false)
private Profile profile;
}
_
@Entity
@Table(name = "\"User\"", uniqueConstraints = { @UniqueConstraint(columnNames = "Username") })
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id", unique = true, nullable = false)
private long id;
@Column(name = "Username", nullable = false, unique = true, length = 80)
private String username;
@Column(name = "Password", nullable = false, length = 128)
private String password;
@Valid
@OneToOne(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
private Profile profile;
}
_
@Entity
@Table(name = "Address")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "FullAddress", nullable = false, unique = false, length = 100)
private String fullAddress;
@Column(name = "City", nullable = false, unique = false, length = 100)
private String city;
@Column(name = "PostalCode", nullable = false, unique = false, length = 100)
private String postalCode;
@OneToOne(fetch = FetchType.LAZY, mappedBy = "address", cascade = CascadeType.ALL)
private Profile profile;
}
Between the solutions i found for similar cases than this was:
Being as new as I'm in this.. what i understand is that the ProfileId is receiving null because for some reason, after the insert of the Profile table, the generated id is not yet set on the profile object, which causes that the phone insert fails. But i have no idea how to solve.
In case you need to know how I am persisting the objects...
sessionFactory.getCurrentSession().persist(profile);
And the sessionFactory is autowired. The profile object has something like:
{"phones":[{"phoneNumber":"123456789"}],"user":{"username":"[email protected]","password":"123123123"},"firstName":"Nameeeeee","lastName":"Nameeeeee","birthDate":"02/05/2016", "address":{"fullAddress":"laksjdlkas","city":"alksjdlkasjd","postalCode":"101010"}}
And lastly the full error:
Hibernate:
insert
into
Address
(FullAddress, City, PostalCode)
values
(?, ?, ?)
Hibernate:
select
last_insert_id()
Hibernate:
insert
into
`User` (
Password, Username
)
values
(?, ?)
Hibernate:
select
last_insert_id()
Hibernate:
insert
into
Profile
(AddressId, BirthDate, FirstName, LastName, UserId)
values
(?, ?, ?, ?, ?)
Hibernate:
select
last_insert_id()
Hibernate:
insert
into
Phone
(PhoneNumber, ProfileId)
values
(?, ?)
WARN SqlExceptionHelper::logExceptions:127 - SQL Error: 1048, SQLState: 23000
ERROR SqlExceptionHelper::logExceptions:129 - Column 'ProfileId' cannot be null
Adding Requested Code.
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = { "com.configuration" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {
final static Logger logger = Logger.getLogger(HibernateConfiguration.class);
@Autowired
private Environment environment;
@Bean
public LocalSessionFactoryBean sessionFactoryBean() {
logger.info("Creating LocalSessionFactoryBean...");
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan(new String[] { "com.model" });
sessionFactoryBean.setHibernateProperties(hibernateProperties());
return sessionFactoryBean;
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory);
return transactionManager;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
properties.put("hibernate.temp.use_jdbc_metadata_defaults",
environment.getRequiredProperty("hibernate.temp.use_jdbc_metadata_defaults"));
}
Upvotes: 0
Views: 1805
Reputation: 198
Somewhere in your code you should do this
Phone phone = new Phone();
//... set phone vars
phone.setProfile(profile);
sessionFactory.getCurrentSession().persist(profile);
Upvotes: 1