Hibernate is putting an erroneous/redundant field in one of my tables. Here is what I have:
Code:
@Entity
@Table(name="MEASUREMENTS")
public class MeasurementsEntity {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private Long id = -1L;
@ManyToOne()//fetch=FetchType.EAGER)
@JoinColumn(name="TYPE_ID")
private MeasurementTypeEntity type = null;
@ManyToOne(fetch=FetchType.EAGER,optional=false)
@JoinTable(name="MEASUREMENTS_USER",
joinColumns=@JoinColumn(name="MEASUREMENTS_ID"),
inverseJoinColumns=@JoinColumn(name="USER_ID"))
private UserEntity user = null;
@OneToMany(cascade=CascadeType.ALL,mappedBy="measurements")
@MapKeyColumn(name="DATE")
@MapKeyTemporal(TemporalType.DATE)
private Map<Date, MeasurementEntity> measurements = null;
public MeasurementsEntity() {
}
// standard getters and setters follow...
}
Code for the measurement type:
Code:
@Entity
@Immutable
@Table(name="MEASUREMENT_TYPES")
public class MeasurementTypeEntity {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private Long id = -1l;
@Column(name="MEASUREMENT")
protected String name = "";
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="UNITS")
protected UnitsEntity units = null;
public MeasurementTypeEntity() {
}
// standard getters and setters follow...
}
This is supposed to be a unidirectional many to one relationship where each measurement knows its type, but the type entity does not keep a list of measurements.
Before I ran this, and after the last modification to my code, I dropped the whole database to be sure that hibernate recreated it. Here is the sql output from "show create table measurements" below:
Code:
measurements | CREATE TABLE `measurements` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`TYPE_ID` bigint(20) DEFAULT NULL,
`type` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `FK74878437A55A5C7F` (`id`),
KEY `FK74878437CD2C5E3D` (`type`),
KEY `FK748784379A1CAF43` (`TYPE_ID`),
CONSTRAINT `FK748784379A1CAF43` FOREIGN KEY (`TYPE_ID`) REFERENCES `measuremen
t_types` (`id`),
CONSTRAINT `FK74878437A55A5C7F` FOREIGN KEY (`id`) REFERENCES `users` (`id`),
CONSTRAINT `FK74878437CD2C5E3D` FOREIGN KEY (`type`) REFERENCES `measurement_t
ypes` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
The redundant field in the table is "type", I don't know how it got there. In my annotations for the java field "type" found in Measurements, I have the @JoinColumn to redirect it to use the foreign key of the type entity. So I don't know why hibernate is also putting a "type" field into the sql table.
Not sure this matters, but I will post my test script and the outcome too:
Code:
@Test
public void testAllPersist() {
if (u == null)
Assert.fail("User info is null, failed to init.");
TestBundle tb = makeTestBundle1();
Session s = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction t = null;
try {
t = s.getTransaction();
if (t == null || !t.isActive())
t = s.beginTransaction();
s.save(tb.getDimensionEntity());
s.save(tb.getUnitsEntity());
s.save(tb.getMeasurementTypeEntity());
s.save(tb.getUserEntity());
t.commit();
s = HibernateUtil.getSessionFactory().getCurrentSession();
t = s.beginTransaction();
// the exception is thrown on the following line.
s.save(tb.getMeasurementsEntity()); // save parent, not table owner.
s.save(tb.getMeasurementEntity()); // save child, table owner.
t.commit();
} catch (Exception e) {
if (t != null && t.isActive())
t.rollback();
e.printStackTrace();
Assert.fail("Failed due to exception "+e.getMessage());
} finally {
if (t != null && t.isActive())
t.commit();
}
}
The exception gets thrown as soon as it tries to save the measurements entity.
Outcome:
Code:
Hibernate: insert into DIMENSION (DIMENSION) values (?)
Hibernate: insert into UNITS (CONVERSION_FACTOR, DIMENSION_ID, UNITS) values (?, ?, ?)
Hibernate: insert into MEASUREMENT_TYPES (MEASUREMENT, UNITS) values (?, ?)
Hibernate: insert into USERS (USER_INFO) values (?)
Hibernate: insert into MEASUREMENTS (TYPE_ID) values (?)
org.hibernate.exception.GenericJDBCException: Field 'type' doesn't have a default value
at org.hibernate.exception.internal.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:148)
... lots of irrelevant stack trace members, then...
at com.knapptech.fitnesstracker.entities.TestUser.testAllPersist(TestUser.java:64)
... long stack trace ...
Caused by: java.sql.SQLException: Field 'type' doesn't have a default value
... long stack trace ...
org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:124)
... 57 more