I am inserting a row into an Oracle table in a Spring Boot application. The Primary Key needs to be generated using annotations. I have an entity model that represents the table:
#Entity
#Table(name="PURCH_TENDR")
public class LhlPurchTendrModel implements Serializable {
#Id
#GeneratedValue(generator = "uuid2")
#GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
#Column(name="PURCH_TENDR_ID")
private String purchTendrId;
#Column(name="CREATED_BY_NM")
private String createdByNm;
#Column(name="CREATED_DT")
private Timestamp createdDt;
#Column(name="UPDATED_BY_NM")
private String updatedByNm;
#Column(name="UPDATED_DT")
private Timestamp updatedDt;
#Column(name="MODIFY_BY_NM")
private String modifyByNm;
#Column(name="MODIFY_DT")
private Timestamp modifyDt;
#Column(name="CARRIER_TENDER_ID")
private long CarrierTenderId;
#Column(name="EVENT_GMT_TM")
private Timestamp EventGmtTm;
#Column(name="PURCH_COST_ID")
private int PurchCostId;
#Column(name="LAT")
private float Lat;
#Column(name="LON")
private float Lon;
#Column(name="CITY_NM")
private String cityNm;
#Column(name="STATE_CD")
private String stateCd;
#Column(name="CARER_EDI_NBR")
private String carerEdiNbr;
#Column(name="EVENT_STAT_CD")
private String eventStatCd;
#Column(name="ETN_TM")
private Timestamp EtnTm;
#Column(name="PCKUP_NBR")
private String PickupNbr;
#Column(name="VIN")
private String Vin;
#Column(name="EQUIP_NBR")
private String EquipNbr;
#Column(name="EQUIP_PREFIX")
private String EquipPrefix;
There are also getters and setters for these member variables.
I use a Repository class to implements a jdbctemplate to insert the row.
When I use this variation of the insert, I get the error that the column type is invalid:
public boolean insertPurchaseInfo(LhlPurchTendrModel lhlPurchTendrModel) throws SQLException {
boolean success= false;
String ds = lhlJdbcTemplate.getDataSource().getConnection().getSchema();
LOGGER.info("Schema and Insert Purchase Info {}", ds);
String insertSequenceNbrSQLStatement = "INSERT INTO purch_tendr(created_by_nm, created_dt, modify_by_nm, modify_dt, carrier_tender_id, purch_cost_id, event_stat_cd, equip_nbr, equip_prefix) " +
"VALUES (?, SYSDATE, ?, SYSDATE, ?, ?, ?, ?, ?)";
try{
int rowsInserted = lhlJdbcTemplate.update(
insertSequenceNbrSQLStatement,
new Object[] {lhlPurchTendrModel});
if(rowsInserted > 0){
success = true;
}
}
When I try to insert using this code, I get the error 'cannot insert NULL into table Purch_Tendr column Purch_Tendr_Id.
public boolean insertPurchaseInfo(LhlPurchTendrModel lhlPurchTendrModel) throws SQLException {
boolean success= false;
String ds = lhlJdbcTemplate.getDataSource().getConnection().getSchema();
LOGGER.info("Schema and Insert Purchase Info {}", ds);
String insertSequenceNbrSQLStatement = "INSERT INTO purch_tendr(created_by_nm, created_dt, modify_by_nm, modify_dt, carrier_tender_id, purch_cost_id, event_stat_cd, equip_nbr, equip_prefix) " +
"VALUES (?, SYSDATE, ?, SYSDATE, ?, ?, ?, ?, ?)";
try{
int rowsInserted = lhlJdbcTemplate.update(
insertSequenceNbrSQLStatement,
new Object[]{lhlPurchTendrModel.getCreatedByNm(), lhlPurchTendrModel.getModifyByNm(), lhlPurchTendrModel.getCarrierTenderId(), lhlPurchTendrModel.getPurchCostId(),
lhlPurchTendrModel.getEventGmtTm(), lhlPurchTendrModel.getEquipNbr(), lhlPurchTendrModel.getEquipPrefix()});
if(rowsInserted > 0){
success = true;
}
}
I am not sure how to use the #Entity class with JdbcTemplate. How do I indicate to JdbcTemplate to generate the primary key value?
You can't because #Entity and all annotations you use such as #GeneratedValue, #GenericGenerator etc come from JPA while JdbcTemplate behind scene is based on JDBC only which does not know anything about JPA.
If you want to use JPA to manage your data , what you need to look is to choose a JPA implementation (e.g Hibernate is a popular one) and study how to use it through JPA interface but not looking at JdbcTemplate.
Once you get the basic ideas to manage data using JPA , you may consider to look at spring data which is a more high level tool build on top of pure JPA that can help to implement repository / DAO kind of stuff for managing and querying the data.
Related
I am using spring boot data jpa as below
#Entity
#Table(name = "invoice")
#Getter
#Setter
#ToString
public class Invoice {
#Id
#Column(name = "inv_id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private BigInteger invId;
#Column(name = "external_id")
private String externalInvoiceId;
#Column(name = "amount")
private double amount;
#JsonIgnore
#JsonIgnoreProperties
#Column(name = "status")
private int status;
#JsonProperty("status")
#Transient
private String invoiceStatus;
public String getInvoiceStatus() {
switch (this.status){
case 1:
return "INITIATED";
case 2:
return "CANCELLED";
case 3:
return "SUCCESS";
case 4:
return "FAILURE";
default:
return "IN PROGRESS";
}
}
#CreationTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "created_at")
private Date createdAt;
#UpdateTimestamp
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "updated_at")
private Date updatedAt;
#PostPersist
public void updateExternalID() {
this.externalInvoiceId="G".concat(String.valueOf(this.invId.multiply(BigInteger.valueOf(1000))))
.concat(String.valueOf(Instant.now().getEpochSecond()));
}
}
Am accesing this entiry via repository as below
public interface InvoicesRepository extends JpaRepository<Invoice, BigInteger> {
}
At my #Service am performing the below operation
#Autowired
private InvoicesRepository myInvoicesRepository;
Invoice transactionInvoice = new Invoice();
transactionInvoice.setAmount(200.0);
transactionInvoice.setStatus(1);
Invoice savedInvoice = myInvoicesRepository.save(transactionInvoice);
Am using savedInvoice and trying to update the status. Either it is not updating the status properly nor I could not find the record in database too.
There are no rollback present
Below are the logs I could see insert statements are present
[XNIO-1 task-1] DEBUG org.hibernate.SQL.logStatement -
/* insert com.min.app.model.Invoice
*/ insert
into
invoice
(amount, created_at, external_inv_id, status, updated_at)
values
(?, ?, ?, ?, ?)
Hibernate:
/* insert com.min.app.model.Invoice
*/ insert
into
invoice
(amount, created_at, external_inv_id, status, updated_at)
values
(?, ?, ?, ?, ?)
After the status updates I tried printing the savedInvoice could see the below in logs
Invoice(invId=58, externalInvoiceId=G580001575271905, amount=185.0 status=4, invoiceStatus=FAILURE, createdAt=Mon Dec 02 13:01:45 IST 2019, updatedAt=Mon Dec 02 13:01:45 IST 2019)
The above record I could not see in the table.
What am I doing wrong?
you need to perform transactions in a function call as follows and put your #Autowired repository in Global level ass follows.
class whatever{
#Autowired
private InvoicesRepository myInvoicesRepository;
//call this function
void doSomething(){
Invoice transactionInvoice = new Invoice();
transactionInvoice.setAmount(200.0);
transactionInvoice.setStatus(1);
Invoice savedInvoice = myInvoicesRepository.save(transactionInvoice);
}
}
I have two tables with a one-to-many relationship. I want to fetch those records and insert into another database which having same table by changing the primary key.
My application entity class
#Entity
#Table(name = "EM_APPLICATION")
public class ApplicationTable {
#Id
private int APPLICATION_ID;
#Id
private String CUSTOMER_ID;
private String LAST_NAME;
private String FIRST_NAME;
#OneToMany( fetch = FetchType.EAGER,cascade = CascadeType.ALL)
#JoinColumns({ #JoinColumn(name = "CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID"),
#JoinColumn(name = "APPLICATION_ID", referencedColumnName = "APPLICATION_ID") })
private Set<AddressTable> address;
//Getters and setters
}
Address entity class..
#Entity
#Table(name="EM_APPL_ADDRESS")
public class AddressTable{
#Id
private int APPLICATION_ID;
#Id
private String CUSTOMER_ID;
#Id
private String ADDRESS_TYPE;
//Getters and setters
}
I have to execute a method for fetching records from DB using hibernate:
public void execute(String applId, String customerId) {
Session session = HibernateQAUtil.openSession();
Transaction tx = session.beginTransaction();
String hql = "FROM ApplicationTable WHERE CUSTOMER_ID =:CUSTOMER_ID AND APPLICATION_ID =:APPLICATION_ID";
Query query = session.createQuery(hql);
query.setParameter("CUSTOMER_ID", customerId);
query.setParameter("APPLICATION_ID", Integer.parseInt(applId));
List<ApplicationTable> list = query.list();
tx.commit();
session.close();
ApplicationTable applVO = list.get(0);
insertApplication(applVO );
}
After fetching the records, I am changing APPLICATION_ID, CUSTOMER_ID and some other columns in address table and after inserting in another database.
private void insertApplication(ApplicationTable emApplVO) {
applVO.setAPPLICATION_ID(123456);
applVO.setCUSTOMER_ID("88888888");
Set<AddressTable> addressSet = emApplVO.getAddress();
for (AddressTable address : addressSet) {
address.setAPPLICATION_ID(123456);
address.setCUSTOMER_ID("88888888");
address.setZIP(500032);
}
Session session1 = HibernateUtil.openSession();
Transaction beginTransaction = session1.beginTransaction();
session1.save(emApplVO);
beginTransaction.commit();
session1.close();
}
Hibernate queries in console log are... (below mentioned queries are too large so copied to some extent only..)
Hibernate: select em_applica0_.CUSTOMER_ID as CUSTOMER1_0_,em_applica0_.APPLICATION_ID as APPLICAT2_0_,em_applica0_.ARCHIVE_IND as ARCHIVE8_0_ where em_applica0_.CUSTOMER_ID=? and em_applica0_.APPLICATION_ID=?
Hibernate: select address0_.CUSTOMER_ID as CUSTOMER1_0_1_, address0_.APPLICATION_ID as APPLICAT2_0_1_, address0_.ADDRESS_TYPE as ADDRESS3_1_0_ where em_applica0_.CUSTOMER_ID=? and em_applica0_.APPLICATION_ID=?
Hibernate: insert into EM_APPLICATION (CUSTOMER_ID, APPLICATION_ID, APPLICATION_NBR, APPLICATION_STATUS, APPLICATION_TYPE) values (?, ?, ?, ?)
Hibernate: insert into EM_APPL_ADDRESS (CUSTOMER_ID, APPLICATION_ID, ADDRESS_TYPE) values (?, ?, ?)
Question 1: in the insert method, I have assigned address to addresSet and made some changes in addresSet, after making those changes, I am not assigned the addressSet to applVO (i.e. not written applVO.setAddress(addresSet )) but it inserted a record with updated values into the Address table. What is happening here?
When I am changing code inside insertApplication(ApplicationTable emApplVO) method to
private void insertApplication(ApplicationTable emApplVO) {
applVO.setAPPLICATION_ID(123456);
applVO.setCUSTOMER_ID("88888888");
Set<AddressTable> addressSet = emApplVO.getAddress();
Set<AddressTable> newAddressSet = new HashSet<AddressTable>();
for (AddressTable address : newAddressSet) {
address.setAPPLICATION_ID(emApplVO.getAPPLICATION_ID());
address.setCUSTOMER_ID(emApplVO.getCUSTOMER_ID());
address.setZIP(500032);
newAddressSet.add(address);
}
emApplVO.setAddress(null);
emApplVO.setAddress(newAddressSet);
Session session1 = HibernateUtil.openSession();
Transaction beginTransaction = session1.beginTransaction();
session1.save(emApplVO);
beginTransaction.commit();
session1.close();
}
Hibernate queries in console log are... It also executing update ...
Hibernate: select em_applica0_.CUSTOMER_ID as CUSTOMER1_0_,em_applica0_.APPLICATION_ID as APPLICAT2_0_,em_applica0_.ARCHIVE_IND as ARCHIVE8_0_ where em_applica0_.CUSTOMER_ID=? and em_applica0_.APPLICATION_ID=?
Hibernate: select address0_.CUSTOMER_ID as CUSTOMER1_0_1_, address0_.APPLICATION_ID as APPLICAT2_0_1_, address0_.ADDRESS_TYPE as ADDRESS3_1_0_ where em_applica0_.CUSTOMER_ID=? and em_applica0_.APPLICATION_ID=?
Hibernate: insert into EM_APPLICATION (CUSTOMER_ID, APPLICATION_ID, APPLICATION_NBR, APPLICATION_STATUS, APPLICATION_TYPE) values (?, ?, ?, ?)
Hibernate: insert into EM_APPL_ADDRESS (CUSTOMER_ID, APPLICATION_ID, ADDRESS_TYPE) values (?, ?, ?)
update EM_APPL_ADDRESS set CUSTOMER_ID=?, APPLICATION_ID=? where CUSTOMER_ID=? and APPLICATION_ID=? and ADDRESS_TYPE=?
Question 2: why is the update query executed?
Question 3: while using List<AddressTable> instead of Set<AddressTable>, I got some errors. What is the difference?
Boot,Jpa and hibernate to persist a one-many relation between venues and events.
The error i'm retrieving is
org.h2.jdbc.JdbcSQLException: NULL not allowed for column "VENUE_LOCATION"; SQL statement:
insert into event (id, date, description, media_ref, num_ratings, performer, performer_media, title, total_rating) values (null, ?, ?, ?, ?, ?, ?, ?, ?) [23502-192]
I've tried saving the parent(Venue) class first and exclusively but that produces the same error.
Venue
public class Venue
{
#Id
private String name;
#Id
private String location;
#OneToOne(mappedBy = "venue",cascade = CascadeType.ALL)
#JoinColumn(name="id")
private VenueUser venueUser;
private String mediaRef;
private int rating;
#OneToMany(fetch=FetchType.LAZY,mappedBy = "venue",cascade = CascadeType.ALL)
private Set<Event> events;
//Constructors getters and setters below
Event
#Entity
public class Event
{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String title;
private String description;
private String performer;
private String[] performerMedia;
private Calendar[] date;
#Transient
private double avgRating;
private int numRatings;
private int totalRating;
private String mediaRef;
#MapsId("name")
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name="Venue_name",referencedColumnName = "name"),
#JoinColumn(name="venue_location",referencedColumnName = "location")
})
private Venue venue;
//Constructors getters and setters below
Controller
#RequestMapping(value = "/event",method=RequestMethod.POST)
public ResponseEntity addEvent(#RequestBody Event event)
{
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName(); //get logged in username
Venue venue = userVenueRepository.findByEmail(name).getVenue();
event.setVenue(venue);
venue.addEvent(event);
if(eventRepository.saveAndFlush(event).equals(event)&&venueRepository.saveAndFlush(venue).equals(venue))
{
return new ResponseEntity(HttpStatus.CREATED);
}
else
{
return new ResponseEntity(HttpStatus.CONFLICT);
}
}
insert into event (id, date, description, media_ref, num_ratings, performer, performer_media, title, total_rating) values (null, ?, ?, ?, ?, ?, ?, ?, ?)
You need to set id to your Event entity. Better use #GeneratedValue annotation with AUTO, like here https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/java/org/springframework/data/jpa/domain/AbstractPersistable.java
or use class AbstractPersistable as parent entity.
Error says that location field of Venue entity is null which cannot be as it is primary key.
You have two options for persisting Event object.
First persist Venue [Parent] Entity and then Persist as many Event [Child] entities as you want.Set venue field in event entity. You need to save Parent entity only once.
If you want to persist both parent and child at once, you can specify cascade = CascadeType.PERSIST in Event Entity and then save child entity.
Ok so I managed to fixed this and in hindsight I shouldn't of blindly followed a tutorial, I wasn't to sure what the #MapsId did so I removed it and everything started working.If anyone could explain what #MapsId does and why it was causing problems that would be appreciated.
You can try this too.
this way you don't need to add parent entry inside child object.
Remove mappedBy form Venue entity
Then add below code inside the Venue entity before Set<Event>
#JoinColumns({
#JoinColumn(name="Venue_name",referencedColumnName = "name"),
#JoinColumn(name="venue_location",referencedColumnName = "location")
})
Remove #JoinColumns and #MapsId from Event entity
Then you don't need to write
event.setVenue(venue);
Hope it helps.
im having difficulty inserting datas to database table from java classes. I'm getting "Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'id' cannot be null"... I did some digging and couldn't figure it out. Let me post my codes... before that i explain what i want to do... This project contains Servlet class,JSP , and java classes. I'm using JSP html Form to get datas and records them to into a database. Codes here...
#Entity
#Table(name="\"Leave\"")
public class Leave implements Serializable{
/**
*
*/
private static final long serialVersionUID = 9088190714759727299L;
#Id
#Column(name="id",nullable=false,updatable=false)
private Long id;
//#OneToOne(mappedBy=)
#GeneratedValue(strategy = GenerationType.AUTO)
#JoinColumn(name = "person_id",referencedColumnName="id")
private Person person;
//#Enumerated(LeaveType)
#Column(name="leavetype")
private LeaveType leavetype;
#Temporal(TemporalType.DATE)
#Column(name="prepdate")
private Date prepdate;
#Temporal(TemporalType.DATE)
#Column(name="startdate")
private Date startdate;
#Temporal(TemporalType.DATE)
#Column(name="enddate")
private Date enddate;
#Temporal(TemporalType.DATE)
#Column(name="oldstartdate")
private Date oldStartdate;
#Temporal(TemporalType.DATE)
#Column(name="oldenddate")
private Date oldEnddate;
#Column(name="workday")
private String workday;
#Column(name="calendarday")
private String calendarday;
#Column(name="reason")
private String reason;
getters setters....
#Entity
#Table(name="\"Person\"")
public class Person implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2532993385565282772L;
#Id
#Column(name="id",nullable=false,updatable=false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String surname;
private String sskno;
private String workstartdate;
private String address;
private String telno;
#OneToMany
private List<Leave> leaves;
AND MY SERVLET CLASS IS....
#WebServlet("/LeaveServlet")
public class LeaveServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String PERSISTENCE_UNIT_NAME = "EmployeeLeaveForm";
private static EntityManagerFactory emf;
public LeaveServlet() {
super();
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager entityManager = emf.createEntityManager();
try {
PrintWriter out = response.getWriter();
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/FormInterface.jsp");
Person person = new Person();
Leave leave = new Leave();
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
Date date = new Date();
String choosenType = request.getParameter("leavetype");
// LEAVING
// TYPES---------------------------------------------------------------------------------------------------
if (choosenType == null) {
request.setAttribute("leaveTypeError",
"Izin turunu giriniz.");
requestDispatcher.forward(request, response);
return;
}
else if (choosenType.equals(LeaveType.ANNUAL.toString())) {
leave.setLeavetype(LeaveType.ANNUAL);
} else if (choosenType.equals(LeaveType.MARRIAGE.toString())) {
leave.setLeavetype(LeaveType.MARRIAGE);
} else if (choosenType.equals(LeaveType.FEEDING.toString())) {
leave.setLeavetype(LeaveType.FEEDING);
} else if (choosenType.equals(LeaveType.MEDICAL.toString())) {
leave.setLeavetype(LeaveType.MEDICAL);
} else if (choosenType.equals(LeaveType.MATERNITY.toString())) {
leave.setLeavetype(LeaveType.MATERNITY);
} else if (choosenType.equals(LeaveType.OTHER.toString())) {
leave.setLeavetype(LeaveType.OTHER);
leave.setReason(request.getParameter("reason"));
if (leave.getReason() != null) {
} else if (leave.getReason() == null) {
request.setAttribute("errorNoReason",
"Please enter a reason");
requestDispatcher.forward(request, response);
return;
}
} else if (choosenType.equals(LeaveType.UNPAID.toString())) {
leave.setLeavetype(LeaveType.UNPAID);
leave.setReason(request.getParameter("reason"));
if (leave.getReason() != null) {
} else if (leave.getReason() == null) {
request.setAttribute("errorNoReason",
"Please enter a reason");
requestDispatcher.forward(request, response);
return;
}
}
// PASSING PARAMETERS TO LOCAL
// VARIABLES---------------------------------------------------------------------------
String prepdate = dateFormat.format(date);
String startdate = request.getParameter("startdate");
String enddate = request.getParameter("enddate");
String oldStartdate = request.getParameter("oldStartdate");
String oldEnddate = request.getParameter("oldEnddate");
person.setName(request.getParameter("name"));
person.setSurname(request.getParameter("surname"));
person.setSskno(request.getParameter("sskno"));
person.setworkStartdate(request.getParameter("workStarted")); // DBden
person.setAddress(request.getParameter("address"));
person.setTelno(request.getParameter("telephone"));
leave.setCalendarday(request.getParameter("calendarday"));
leave.setWorkday(request.getParameter("workday"));
leave.setPrepdate(dateFormat.parse(prepdate));
leave.setStartdate(dateFormat.parse(startdate));
leave.setEnddate(dateFormat.parse(enddate));
leave.setOldStartdate(dateFormat.parse(oldStartdate));
leave.setOldEnddate(dateFormat.parse(oldEnddate));
// Checking the consistency of the
// time----------------------------------------------------------------------------
if (((leave.getEnddate() != null) && (leave.getOldEnddate() != null))) {
entityManager.getTransaction().begin();
entityManager.persist(leave);
entityManager.getTransaction().commit();
//db den return
//info
}
else {
if (leave.getEnddate() == null) {
request.setAttribute("errorMessage1", "Please enter dates correctly");
}
if (leave.getOldEnddate() == null) {
request.setAttribute("errorMessage2", "Please enter date correctly");
}
requestDispatcher.forward(request, response);
}
} catch (Throwable exc) {
System.out.println(exc);
}
finally {
// Close the database connection:
if (entityManager.getTransaction().isActive())
entityManager.getTransaction().rollback();
entityManager.close();
}
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
}
}
And errors...
[EL Info]: 2013-07-29 10:05:47.872--ServerSession(76232710)--EclipseLink, version: Eclipse Persistence Services - 2.5.0.v20130507-3faac2b
[EL Info]: connection: 2013-07-29 10:05:48.207--ServerSession(76232710)--file:/C:/Users/VAIO/Desktop/workspace - Kopya/.metadata/.plugins/org.eclipse.wst.server.core/tmp1/wtpwebapps/EmployeeLeaveForm/WEB-INF/classes/_EmployeeLeaveForm login successful
[EL Warning]: 2013-07-29 10:05:48.292--UnitOfWork(1213364484)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'id' cannot be null
Error Code: 1048
Call: INSERT INTO `Leave` (id, calendarday, enddate, leavetype, oldenddate, oldstartdate, prepdate, reason, startdate, workday, person_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
bind => [11 parameters bound]
Query: InsertObjectQuery(com.eteration.leavesystem.model.Leave#4fff5f4f)
javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'id' cannot be null
Error Code: 1048
Call: INSERT INTO `Leave` (id, calendarday, enddate, leavetype, oldenddate, oldstartdate, prepdate, reason, startdate, workday, person_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
bind => [11 parameters bound]
Query: InsertObjectQuery(com.eteration.leavesystem.model.Leave#4fff5f4f)
I also use mysql and i created a database table.
WHY am I getting these exceptions.. And seriously i did digging but nothing work for me pls help me thanks...
EDIT-
[EL Info]: 2013-07-29 11:05:56.944--ServerSession(624062858)--EclipseLink, version: Eclipse Persistence Services - 2.5.0.v20130507-3faac2b
[EL Info]: connection: 2013-07-29 11:05:57.283--ServerSession(624062858)--file:/C:/Users/VAIO/Desktop/workspace - Kopya/.metadata/.plugins/org.eclipse.wst.server.core/tmp1/wtpwebapps/EmployeeLeaveForm/WEB-INF/classes/_EmployeeLeaveForm login successful
[EL Warning]: 2013-07-29 11:05:57.362--ClientSession(72318077)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'eteration.sequence' doesn't exist
Error Code: 1146
Call: UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
bind => [2 parameters bound]
Query: DataModifyQuery(name="SEQUENCE" sql="UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?")
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'eteration.sequence' doesn't exist
Error Code: 1146
Call: UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
bind => [2 parameters bound]
Query: DataModifyQuery(name="SEQUENCE" sql="UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?")
It seems you try to persist your entity and its id remains null. That's why your get a constraint violation error.
To simply solve this error I suggest you to try create your database table using auto-incrementation option on your id. It should solve your problem, I guess.
It means supply data(from some source and of a type that matches the db field type for "id") for the "id" column to insert into the database with the call. Somewhere you are not supplying and "id" data to the query in your code.
Add
#GeneratedValue(strategy = GenerationType.AUTO)
to your Leave ID
#Id
#Column(name="id",nullable=false,updatable=false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
or create Leave constructor with Long Id arg to set your id. So, you wont be able to create Leave instance with id set to null.
Is it missing GeneratedValue annotation in id field?
If you use AUTO generation, the id generation will be depend on Persistence Provider.
You might need to set auto increment for primary key.
#Entity
#Table(name="Leave")
public class Leave implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="id",nullable=false,updatable=false)
private Long id;
#OneToOne
#GeneratedValue(strategy = GenerationType.AUTO) --> remove this code
#JoinColumn(name = "person_id", referencedColumnName="id")
private Person person;
}
You are not setting the id in your code and you are not telling your JPA provider to generate it either.
You can use the #GeneratedValue annotation to tell your JPA provider to generate your id.
Here is an example
I figure it out my problem thank you guys for help. I solved my problem in that way... eclipselink needs sequence table on my database and i created one then it works... Thank you again :)
I want to persist a mail entity which has some resources (inline or attachment). First I related them as a bidirectional relation:
#Entity
public class Mail extends BaseEntity {
#OneToMany(mappedBy = "mail", cascade = CascadeType.ALL, orphanRemoval = true)
private List<MailResource> resource;
private String receiver;
private String subject;
private String body;
#Temporal(TemporalType.TIMESTAMP)
private Date queued;
#Temporal(TemporalType.TIMESTAMP)
private Date sent;
public Mail(String receiver, String subject, String body) {
this.receiver = receiver;
this.subject = subject;
this.body = body;
this.queued = new Date();
this.resource = new ArrayList<>();
}
public void addResource(String name, MailResourceType type, byte[] content) {
resource.add(new MailResource(this, name, type, content));
}
}
#Entity
public class MailResource extends BaseEntity {
#ManyToOne(optional = false)
private Mail mail;
private String name;
private MailResourceType type;
private byte[] content;
}
And when I saved them:
Mail mail = new Mail("asdasd#asd.com", "Hi!", "...");
mail.addResource("image", MailResourceType.INLINE, someBytes);
mail.addResource("documentation.pdf", MailResourceType.ATTACHMENT, someOtherBytes);
mailRepository.save(mail);
Three inserts were executed:
INSERT INTO MAIL (ID, BODY, QUEUED, RECEIVER, SENT, SUBJECT) VALUES (?, ?, ?, ?, ?, ?)
INSERT INTO MAILRESOURCE (ID, CONTENT, NAME, TYPE, MAIL_ID) VALUES (?, ?, ?, ?, ?)
INSERT INTO MAILRESOURCE (ID, CONTENT, NAME, TYPE, MAIL_ID) VALUES (?, ?, ?, ?, ?)
Then I thought it would be better using only a OneToMany relation. No need to save which Mail is in every MailResource:
#Entity
public class Mail extends BaseEntity {
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#JoinColumn(name = "mail_id")
private List<MailResource> resource;
...
public void addResource(String name, MailResourceType type, byte[] content) {
resource.add(new MailResource(name, type, content));
}
}
#Entity
public class MailResource extends BaseEntity {
private String name;
private MailResourceType type;
private byte[] content;
}
Generated tables are exactly the same (MailResource has a FK to Mail). The problem is the executed SQL:
INSERT INTO MAIL (ID, BODY, QUEUED, RECEIVER, SENT, SUBJECT) VALUES (?, ?, ?, ?, ?, ?)
INSERT INTO MAILRESOURCE (ID, CONTENT, NAME, TYPE) VALUES (?, ?, ?, ?)
INSERT INTO MAILRESOURCE (ID, CONTENT, NAME, TYPE) VALUES (?, ?, ?, ?)
UPDATE MAILRESOURCE SET mail_id = ? WHERE (ID = ?)
UPDATE MAILRESOURCE SET mail_id = ? WHERE (ID = ?)
Why this two updates? I'm using EclipseLink, will this behaviour be the same using another JPA provider as Hibernate? Which solution is better?
UPDATE:
- If I don't use #JoinColumn EclipseLink creates three tables: MAIL, MAILRESOURCE and MAIL_MAILRESOURCE. I think this is perfectly logic. But with #JoinColumn it has information enough for creating only two tables and, in my opinion, do only inserts, with no updates.
When you use a #JoinColumn in a OneToMany you are defining a "unidirectional" one to many, which is a new type of mapping added in JPA 2.0, this was not supported in JPA 1.0.
This is normally not the best way to define a OneToMany, a normal OneToMany is defined using a mappedBy and having a ManyToOne in the target object. Otherwise the target object has no knowledge of this foreign key, and thus the separate update for it.
You can also use a JoinTable instead of the JoinColumn (this is the default for OneToMany), and then there is no foreign key in the target to worry about.
There is also a fourth option. You could mark the MailResource as an Embeddable instead of Entity and use an ElementCollection.
See,
http://en.wikibooks.org/wiki/Java_Persistence/OneToMany
Mapped by defines owning side of the relation ship so for JPA it gives better way to handle associations. Join Column only defines the relationship column. Since JPA is completely reflection based framework I could think of the optimization done for Mapped by since it is easy find owning side this way.