I'm using the latest version of Hibernate Tools from JBoss Studio / Eclipse to generate Java POJOs from my database schema.
When there is a get method that gets further objects I want to have these returned in a specific order. Obviously I can just edit the class file however these changes will then be lost if these files are re-generated if there are any further schema changes.
Research has showed it should be possible to add these options using hibernate reverse engineering XML config or possibly a hibernate hbm xml file.
I can't seem to get these to work and am hoping somebody could provide an example config that would work.
I have created a very simple DB to illustrate the problem.
SQL Schema:
--
-- Table structure for table `pupil`
--
DROP TABLE IF EXISTS `pupil`;
/*!40101 SET #saved_cs_client = ##character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `pupil` (
`ID` int(11) NOT NULL,
`school_id` int(11) NOT NULL,
`forename` varchar(100) NOT NULL,
`surname` varchar(100) NOT NULL,
`gender` enum('M','F') NOT NULL,
PRIMARY KEY (`ID`),
KEY `fk_pupils_schools_idx` (`school_id`),
CONSTRAINT `fk_pupils_schools` FOREIGN KEY (`school_id`) REFERENCES `school` (`ID`) ON DELETE NO ACTION ON UPDATE NO ACTION)
ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = #saved_cs_client */;
--
-- Table structure for table `school`
--
DROP TABLE IF EXISTS `school`;
/*!40101 SET #saved_cs_client = ##character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `school` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = #saved_cs_client */;
This results in two POJOs.
Pupil.java
package hibernateExample.db;
// Generated 20-Sep-2014 15:34:31 by Hibernate Tools 4.0.0
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* Pupil generated by hbm2java
*/
#Entity
#Table(name = "pupil", catalog = "test")
public class Pupil implements java.io.Serializable {
private int id;
private School school;
private String forename;
private String surname;
private String gender;
public Pupil() {
}
public Pupil(int id, School school, String forename, String surname,
String gender) {
this.id = id;
this.school = school;
this.forename = forename;
this.surname = surname;
this.gender = gender;
}
#Id
#Column(name = "ID", unique = true, nullable = false)
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "school_id", nullable = false)
public School getSchool() {
return this.school;
}
public void setSchool(School school) {
this.school = school;
}
#Column(name = "forename", nullable = false, length = 100)
public String getForename() {
return this.forename;
}
public void setForename(String forename) {
this.forename = forename;
}
#Column(name = "surname", nullable = false, length = 100)
public String getSurname() {
return this.surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
#Column(name = "gender", nullable = false, length = 2)
public String getGender() {
return this.gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
School.java. The getPupils method needs to have an OrderBy annotation added on POJO creation. This probably needs to be a List rather than a Set too?
package hibernateExample.db;
// Generated 20-Sep-2014 15:34:31 by Hibernate Tools 4.0.0
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
/**
* School generated by hbm2java
*/
#Entity
#Table(name = "school", catalog = "test")
public class School implements java.io.Serializable {
private Integer id;
private String name;
private Set<Pupil> pupils = new HashSet<Pupil>(0);
public School() {
}
public School(String name, Set<Pupil> pupils) {
this.name = name;
this.pupils = pupils;
}
#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 = "name", length = 200)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "school")
public Set<Pupil> getPupils() {
return this.pupils;
}
public void setPupils(Set<Pupil> pupils) {
this.pupils = pupils;
}
}
Thanks
Example to add the an annotation via reverse engineering xml:
You can see how easy it is to tweak the scope class mete attibute in below example.
<table name="organization">
<meta attribute="scope-class">#Proxy(lazy=false) public</meta>
<meta attribute="extra-import">org.hibernate.annotations.Proxy</meta>
....rest of config.....
</table>
You could on a field level using scope-field attribute.
Full meta attributes at this link
Related
I'm struggling with this problem. I have table "Cities" which has foreign key to table "Countries" with country_id referenced to country from which is city. In my web application I can list all the data from "Cities" table but I can't find a way to list name of country. This is my service class method.
public List<City> listAll() {
List<City> cities = repo.findAll();
return cities;
}
In "City" entity I have field Country by which I can find in method name of country but I don't know how to return it together with cities.
Addition:
#GetMapping("/cities")
public String getAllCities(Model model) {
List<City> listCities = service.listAll();
model.addAttribute("showListCities", listCities);
return "cities";
}
City.java:
package com.bookflight.BookFlight.gradovi;
import com.bookflight.BookFlight.drzave.Drzave;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "cities")
public class City {
#Id
#Column(name = "city_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(nullable = false, length = 45, name = "city_name")
private String city_name;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "cou_id", referencedColumnName = "cou_id")
private Country countries;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getcity_name() {
return city_name;
}
public void setcity_name(String city_name) {
this.city_name = city_name;
}
public Countries getCountries() {
return countries;
}
public void setCountries(Country countries) {
this.countries = countries;
}
}
NOTE: Every variable name here is in my native language so I literally translated it word by word to better understand your solution afterwards.
You have add FetchType to the #ManyToOne annotation arguments:
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinColumn(name = "cou_id", referencedColumnName = "cou_id")
private Country countries;
and her a short description for each fetch type:
FetchType.LAZY will only fire for primary table. If in your code you call any other method that has a parent table dependency then it will fire query to get that table information.
FetchType.EAGER will create join of all table including relevant parent tables directly.
And you can add a method in your city Class to return your country name and this method will be available in your view-layer:
public String getCountryName(){
return countries == null ? null : countries.getName();
//not sure how the country class is implemented
}
I am using JPA createquery API to fetch the data.
Here is my query data
#PersistenceContext
EntityManager entityManager;
#Override
public List<String> fetchAllReleaseNumbers() {
Query query = entityManager.createQuery("SELECT release FROM ReleaseModel", String.class);
return query.getResultList();
}
and here is my pojo class.
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "dbname.tablenamefromDB")
public class ReleaseModel {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "dbcolumnname", unique = true, nullable = false)
private String release;
#Column(name = "dbcolumnname")
private String releaseDesc;
#Column(name = "dbcolumnname")
private Integer releaseStatus;
#Column(name = "dbcolumnname")
private Integer releaseMode;
public String getRelease() {
return release;
}
public void setRelease(String release) {
this.release = release;
}
public String getReleaseDesc() {
return releaseDesc;
}
public void setReleaseDesc(String releaseDesc) {
this.releaseDesc = releaseDesc;
}
public Integer getReleaseStatus() {
return releaseStatus;
}
public void setReleaseStatus(Integer releaseStatus) {
this.releaseStatus = releaseStatus;
}
public Integer getReleaseMode() {
return releaseMode;
}
public void setReleaseMode(Integer releaseMode) {
this.releaseMode = releaseMode;
}
}
Though the table exists in db its throwing not exist.Any ideas where I made mistake.
I tried whether any aliases can be given to the table name.
I am using pojo class name only for createQuery.
TIA.
You should specify a schema name by this way
#Table(schema = "dbname", name = "tablenamefromDB")
You have an incorrect mapping:
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "dbcolumnname", unique = true, nullable = false)
private String release;
I think String can't be auto generated.
Also all your columns have dbcolumnname name.
The issue was that the schema was not specified in the entity class or the user did not login using proxy. If the user login using a proxy access i.e. userName[schemaName] they do not need to specify schema in the entity class. But if the user login using just the userName, they need to specify the schema in the entity. This is to specify where the table can be found in the database.
Based on the following mapping (at the bottom of question) I need to know how to set an specific value in the "department_id" in the Employee class.
Employee
--------------------------------------------
id | firstname | lastname | department_id
--------------------------------------------
1 | David | Smith | 1
Department
-----------
id | name
-----------
1 | Dep A
2 | Dep B
3 | Dep C
saveEmployee method (EmployeeController class):
#RequestMapping(value = "/saveEmployee", method = RequestMethod.POST)
public String saveEmployee(#ModelAttribute("employee") Employee employee){
/* I need to set the department "id" (foreign key) into the Employee
table directly in this method. */
int id = 1; // 2 or 3...
/* The "department_id" in the Employee class should
to receive the "id" value. */
employee.setDepartment(id); // It does not work.
employeeService.saveEmployee(employee);
return "redirect:/employees";
}
Employee class:
#Entity
public class Employee{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String firstname;
private String lastname;
#ManyToOne
#JoinColumn(name = "department_id")
private Department department;
// Getters and Setters
}
Department class:
#Entity
public class Department{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
// Getters and Setters
}
Look carefully at your Employee class:
#Entity
public class Employee{
...
#ManyToOne
#JoinColumn(name = "department_id")
private Department department;
/* THIS IS NOT AN INTEGER DATA TYPE, IT'S A DEPARTMENT DATA TYPE.
SO THE SETTER FOR THIS WILL LOOK SOMEWHAT LIKE THIS:*/
//Setter
public void setDepartment(Department department) {
this.department = department
}
...
// Getters and Setters
}
In order to set a department create an instance your Department and then send it through setter:
#RequestMapping(value = "/saveEmployee", method = RequestMethod.POST)
public String saveEmployee(#ModelAttribute("employee") Employee employee){
int id = 1; // 2 or 3...
Department temporaryDepartment = new Department();
temporaryDepartment.setId(id);
employee.setDepartment(temporaryDepartment);
employeeService.saveEmployee(employee);
return "redirect:/employees";
}
Actually your setDepartment receives a Department instance. So you have to do this:
int id = 1;
Department department = new Department(); //Or you can use Autowired
department.setId(id); // Set Id Department
employee.setDepartment(department); // A Department instance
employeeService.saveEmployee(employee);
return "redirect:/employees";
Actually, You have set Generation strategy as shown below
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
on Department class which means you would want hibernate to generate the ids for you so that you don't have to worry about setting the department id. You just need to set the department name.
Below is the working code, JPAEmployeeTest.java:
package com.chatar.hibernate.receipes.example;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.chatar.hibernate.receipes.example.domain.annotations.Department;
import com.chatar.hibernate.receipes.example.domain.annotations.Employee;
public class JPAEmployeeTest {
public static void main(String[] args) {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory( "employee" );
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
Employee employee = new Employee();
Department department = new Department();
department.setName("Engineering");
employee.setFirstName("Johny");
employee.setLastName("Walker");
employee.setDepartment(department);
entityManager.persist(employee);
entityManager.getTransaction().commit();
entityManager.close();
}
}
And my domain object, Employee.java
package com.chatar.hibernate.receipes.example.domain.annotations;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
#Entity
public class Employee implements Serializable {
private static final long serialVersionUID = -5641563180459243167L;
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private long id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "department_id" )
private Department department;
public long getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
}
And Department.java
package com.chatar.hibernate.receipes.example.domain.annotations;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Department implements Serializable {
private static final long serialVersionUID = -598469568850009702L;
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
My persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="employee" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.chatar.hibernate.receipes.example.domain.annotations.Employee</class>
<class>com.chatar.hibernate.receipes.example.domain.annotations.Department</class>
<properties>
<property name="javax.persistence.jdbc.driver"
value = "org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="javax.persistence.jdbc.url" value = "jdbc:derby://localhost:1527/BookShopDB" />
<property name="javax.persistence.jdbc.user" value="book" />
<property name="javax.persistence.jdbc.password" value = "book" />
<property name="hibernate.dialect" value = "org.hibernate.dialect.DerbyDialect" />
</properties>
</persistence-unit>
</persistence>
My Database output:
ij> select * from employee;
ID |FIRST_NAME |LAST_NAME |DEPARTMENT&
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
163840 |Johny |Walker |1
1 row selected
ij> select * from department;
ID |NAME
----------------------------------------------------------------------------------------------------------------
1 |Engineering
1 row selected
ij>
Note - I'm using GenerationType.TABLE as somehow AUTO was not working for my database i.e. Debry. Also, I have set CascadeType.ALL so that when I save Employee entity, Hibernate saves all references entities e.g. Department in my case.
I have an Entity called Person which has name property as String and person petnames has collection. When mapping to Hibernate I am getting exception. How can I resolve this problem?
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.myapp.struts;
import java.io.Serializable;
import java.util.Set;
import javax.persistence.CollectionTable;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
/**
*
* #author hyva
*/
#Entity
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setPetname(Set<String> petname) {
this.petname = petname;
}
public void setId(Long id) {
this.id = id;
}
private String name;
private Set<String> petname;
#ElementCollection
#CollectionTable(name = "petname", joinColumns =
#JoinColumn(name = "PERSON_ID"))
public Set<String> getPetname() {
return petname;
}
}
*Exception:*
Initial SessionFactory creation failed.org.hibernate.MappingException: Could not determine type for: java.util.Set, for columns: [org.hibernate.mapping.Column(petname)]
Exception in thread "main" java.lang.ExceptionInInitializerError
at com.myapp.struts.HibernateUtil.<clinit>(HibernateUtil.java:28)
at com.myapp.struts.HibernateComplexValue.main(HibernateComplexValue.java:19)
Caused by: org.hibernate.MappingException: Could not determine type for: java.util.Set, for columns: [org.hibernate.mapping.Column(petname)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:266)
aJava Result: 1
Move #CollectionTable over to be an annotation on getPetname as shown below:
private Set<String> petname;
#ElementCollection
#CollectionTable(name = "pets", joinColumns =#JoinColumn(name = "PERSON_ID"))
public Set<String> getPetname(){
return petname;
}
Your annotation #CollectionTable is located after your property petName! Is is a copy/paste error?
You have not mapped your petname column. And your default property name is the same as your table name (petname)...
What is supposed to be the name of the column holding the pet names in this table?
Try adding #Column(name="YOUR_COLUMN_NAME") to force the mapping to this column.
UPDATE 2014-01-29: I have changed relationshis so entity code and error changed too
I have to store some data in a database and my relations are like this:
Order3d 1-----* Draw 1-----* Line
I want to save everything like this:
Order3d o=new Order3d();
//add data to order (lines and draws)
Session s=HibernateUtils.getSessionFactory().openSession();
s.save(o);
s.close();
I don't have runtime error but now my line is not inserted (only order3d and drawfile are saved)
here are my entities (obviously, they are POJO so I didn't copy getters and setters):
#Entity
#Table (name="order3d")
public class Order3d implements Serializable {
private static final long serialVersionUID = -2241346447352903470L;
public enum State {DEMAND, ESTIMATED, PAYED, PENDING, PRODUCED, SENT, DELIVERED};
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column (name="id")
private int id;
#Column (name="person")
private int person;
#Column (name="state", columnDefinition="smallint")
private State state;
#Column (name="labor_expense")
private float laborExpense=0;
#Column (name="travel_expense")
private float travelExpense=0;
#Column (name="validity_date")
private Date validityDate;
#Column (name="demand_date")
private Date demandDate;
#Column (name="estimate_date")
private Date estimateDate;
#Column (name="order_date")
private Date orderDate=null;
#Column (name="modification", columnDefinition="TEXT")
private String modification;
#Column (name="delivery", columnDefinition = "BIT", length = 1)
private Boolean delivery=true;
#OneToMany(mappedBy="order3d", cascade=CascadeType.ALL)
private Set<DrawFile> myDraws=new HashSet<DrawFile>(5);
public void addDrawFile(DrawFile df) {
df.setOrder3d(this);
myDraws.add(df);
}
}
#Entity
#Table (name="draw")
public class DrawFile implements Serializable {
private static final long serialVersionUID = -9024754876558087847L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column (name="id")
private int id;
#Column (name="hashname", columnDefinition="CHAR(64)")
private String hashname;
#Column (name="filename")
private String filename="";
#Column (name="accepted", columnDefinition = "BIT", length = 1)
private Boolean accepted=true;
#Column (name="format")
private String format;
#Column (name="size")
private int size;
#Column(name="width")
short width;
#Column(name="depth")
short depth;
#Column(name="height")
short height;
#OneToMany(mappedBy="draw", cascade=CascadeType.ALL)
private Set<Order3dLine> myLines=new HashSet<Order3dLine>(5);
#ManyToOne
#JoinColumn(name="order3d_id")
private Order3d order3d;
public void addLine(Order3dLine l) {
l.setDraw(this);
myLines.add(l);
}
}
#Entity
#Table (name="line3d")
public class Order3dLine implements Serializable {
private static final long serialVersionUID = 3993578603382571145L;
#NaturalId
#ManyToOne
#JoinColumn(name="draw_id")
private DrawFile draw;
#Column (name="quantity")
private short quantity=0;
#Id
#Column (name="material")
private String material;
#Id
#Column (name="color")
private int color;
#Column(name="produced")
short produced=0;
#Column(name="duration")
short duration=0;
}
Here are my MySQL tables:
CREATE TABLE `draw` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`filename` varchar(255) DEFAULT NULL,
`format` varchar(6) DEFAULT NULL,
`hashname` char(64) DEFAULT NULL,
`accepted` bit(1) NOT NULL DEFAULT b'0',
`size` int(11) NOT NULL DEFAULT '0',
`order3d_id` int(11) NOT NULL,
`width` smallint(6) NOT NULL DEFAULT '0',
`depth` smallint(6) NOT NULL DEFAULT '0',
`height` smallint(6) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
CONSTRAINT `fk_draw_order3d` FOREIGN KEY (`id`) REFERENCES `order3d` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf-8;
/*!40101 SET character_set_client = #saved_cs_client */;
CREATE TABLE `line3d` (
`draw_id` int(11) NOT NULL,
`material` varchar(10) NOT NULL,
`color` int(11) NOT NULL,
`quantity` smallint(6) NOT NULL DEFAULT '0',
`produced` smallint(6) NOT NULL DEFAULT '0',
`duration` smallint(6) NOT NULL DEFAULT '0',
`layers` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`draw_id`,`material`,`color`),
CONSTRAINT `fk_line_draw` FOREIGN KEY (`draw_id`) REFERENCES `draw` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf-8;
CREATE TABLE `order3d` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`person` int(11) DEFAULT NULL,
`state` smallint(6) DEFAULT NULL,
`labor_expense` float DEFAULT NULL,
`travel_expense` float DEFAULT NULL,
`validity_date` date DEFAULT NULL,
`estimate_date` date DEFAULT NULL,
`order_date` date DEFAULT NULL,
`delivery` bit(1) NOT NULL DEFAULT b'0',
`modification` text,
`demand_date` date DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_order_user` (`person`),
CONSTRAINT `fk_order_user` FOREIGN KEY (`person`) REFERENCES `person` (`id`) ON DELETE SET NULL ON UPDATE SET NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf-8;
(1) You have a bi-directional relation between order and order line.
Hibernate expects you to assign order to line like in this convenience method:
#Entity
#Table(name="ORDERS")
public class Order {
[...]
public void addLine(OrderLine line) {
line.setOrder(this);
myLines.add(line);
}
}
See also this thread.
(2) "order" is not accepted as an valid table table name. Choose for example "orders".
(3) You forgot the cascade option on your one-to-one relation between order line and draw. Consider using #Embedded instead of #OneToOne. See Hibernate Doc
I put together minimal working example:
Order:
#Entity
#Table(name = "ORDERS")
public class Order {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column (name = "id")
private Long id;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name="line_id", nullable = false)
private Set<OrderLine> lines = new HashSet<OrderLine>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Set<OrderLine> getLines() {
return lines;
}
public void setLines(Set<OrderLine> lines) {
this.lines = lines;
}
public void addLine(OrderLine line) {
line.setOrder(this);
lines.add(line);
}
}
Order line:
#Entity
#Table(name = "ORDER_LINES")
public class OrderLine {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column (name = "id")
private Long id;
#ManyToOne(fetch = FetchType.EAGER)
private Order order;
#Column(name = "content")
private String content;
#Embedded
private OrderDraw draw;
public OrderDraw getDraw() {
return draw;
}
public void setDraw(OrderDraw draw) {
this.draw = draw;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
}
Order Draw (whatever this is)
#Embeddable
public class OrderDraw {
private int width;
private int height;
public OrderDraw() {
this(0,0);
}
public OrderDraw(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}