Some parent entity value cannot be saved to child entity - java

When i save the job entity i was expecting that the child under job should also reflect in the db. The problem is that the ref_id and revision does not contain any value from the db.
here is the result from mysql db (removed confidential data)
This is my Job entity class
#Entity
#Table(name = "job")
public class Job implements Serializable {
private static final long serialVersionUID = -2075866246194059832L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private long id;
#Column(name = "ref_id")
private String refId;
#Column(name = "revision")
private int revision;
#Column(name = "appname")
private String appName;
#Column(name = "vendor")
private String vendor;
#Column(name = "version")
private String version;
#Column(name = "locale")
private String locale;
#Column(name = "platform")
private String platform;
#Column(name = "tier")
private String tier;
#Column(name = "category")
private String category;
#Column(name = "functional_tag")
private String functional;
#Column(name = "job_start_date")
private Date jobStartDate;
#Column(name = "author")
private String author;
#Enumerated(EnumType.STRING)
private Status status;
#Column(name = "release_version")
private String releaseVersion;
#OneToMany(mappedBy = "job", cascade = CascadeType.PERSIST)
private List<Task> tasks;
}
And here is the child
#Entity
#Table(name = "task")
public class Task implements Serializable {
private static final long serialVersionUID = -7395753611385528546L;
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "module_name")
private String moduleName;
#Column(name = "start_time")
private Date startTime;
#Column(name = "end_time")
private Date endTime;
#Enumerated(EnumType.STRING)
private Status status;
#Column(name = "machine_ip")
private String machineIp;
#Column(name = "data_center")
private String dataCenter;
#Column(name = "description")
private String description;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
#JoinColumns({#JoinColumn(name = "ref_id", referencedColumnName = "ref_id"),
#JoinColumn(name = "revision", referencedColumnName = "revision")})
private Job job;
}
Here is the code that persist the entity
#Service
public class QReaderService {
#Autowired
private JobRepository jobRepository;
#Autowired
private TaskRepository taskRepository;
public boolean addJob(Job job) {
Job previousJob = jobRepository.findByJobRefId(job.getRefId());
if (previousJob == null) {
**jobRepository.save(job);**
return true;
} else {
switch (job.getStatus()) {
case FAILED:
case EXCEPTION:
int revision = 0;
revision += previousJob.getRevision();
previousJob.setStatus(Status.FAILED);
jobRepository.save(previousJob);
break;
}
}
return true;
}
}
This is how i build the job entity
Job job = new Job();
job.setRefId("f78d9as7f98dsa7f97a97f98sda9f7");
job.setAppName("appname");
job.setLocale("locale");
job.setPlatform("platform");
job.setCategory("category");
job.setReleaseVersion("1.1");
job.setStatus(Status.PROCESSING);
job.setAuthor("author");
job.setFunctional("functional");
job.setJobStartDate(new Date());
job.setVersion("1.1");
job.setTier("tier1");
job.setVendor("vendor");
Task task = new Task();
task.setDescription("description");
task.setDataCenter("dataCenter");
task.setStartTime(new Date());
task.setStatus(Status.PROCESSING);
task.setMachineIp("ip");
task.setModuleName("module");
job.setTasks(new ArrayList<Task>(Arrays.asList(task)));
jobRepository.save(job);

To persist child entities when you call save on parent entity, both sides of the relations should be set.
job.setTasks(job.setTasks(new ArrayList<Task>(Arrays.asList(task)));
//Missing line //Important for persistence of child
task.setJob(job);
Hope this helps.

Related

Spring Data JPA Non-key field references in Spring Data JPA

EntityDiagram How to Event(id) refererences to CurriculumVitae(event_id) and FamilyMember(id) refererences to CurriculumVitae(family_member_id)
My code is :
#Getter
#Setter
#ToString
#Data
#Entity
#Table(name = "CurriculumVitaes")
public class CurriculumVitae implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "identity_card_number")
private String identityCardNumber;
#Column(name = "place_for_identity_cards")
private String placeForIdentityCards;
#Column(name = "phone_number")
private String phoneNumber;
#Column(name = "ethnic")
private String ethnic;
#Column(name = "religion")
private String religion;
#Column(name = "family_composition_after_land_reform")
private String familyCompositionAfterLandReform;
#Column(name = "family_member")
private String familyMember;
#Column(name = "education_level")
private String educationLevel;
#Column(name = "language")
private String language;
#Column(name = "qualification")
private String qualification;
#Column(name = "type_of_education")
private String typeOfEducation;
#Column(name = "specialized_training")
private String specializedTraining;
#Column(name = "health_situation")
private String healthSituation;
#Column(name = "tall")
private String tall;
#Column(name = "weight")
private String weight;
#Column(name = "occupation_or_qualification")
private String occupationOrQualification;
#Column(name = "ranks")
private String rank;
#Column(name = "current_salary")
private String currentSalary;
#Column(name = "date_of_enlistment")
private Date dateOfEnlistment;
#Column(name = "date_of_demobilization")
private Date dateOfDemobilization;
#Column(name = "reason")
private String reason;
#OneToMany(mappedBy = "curriculumVitae", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#EqualsAndHashCode.Exclude
#ToString.Exclude
#JsonIgnore
private Collection<Event> event;
#OneToMany(mappedBy = "curriculumVitae", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#EqualsAndHashCode.Exclude
#ToString.Exclude
#JsonIgnore
private Collection<FamilyMember> familyMemberList;
}
But FamilyMembers(curriculum_vitae_id) references to CurriculumVitae(id)*
#Getter
#Setter
#ToString
#Data
#Entity
#Table(name = "FamilyMembers")
public class FamilyMember implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "occupation")
private String occupation;
#Column(name = "august_revolution")
private String augustRevolution;
#Column(name = "resistance_war_against_French_colonialism")
private String resistanceWarAgainstFrenchColonialism;
#Column(name = "activities_from_1955")
private String activitiesFrom1955;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "curriculum_vitae_id", referencedColumnName = "family_member_id")
#EqualsAndHashCode.Exclude
#ToString.Exclude
private CurriculumVitae curriculumVitae;
}

delete call stuck for forever in a Many to One Relationship

Trying to run a delete query on a many-one relationship. But sometime it's stuck for a while when the count of row delete is more then ~50.
Repository:
#Repository
public interface TransitItemRepository extends JpaRepository<TransitItemsMapping, UUID> {
#Modifying
#Transactional
#Query(value="delete from TransitItemsMapping t where t.grouping_form_id=:groupingFormId",nativeQuery = true)
void deleteByGroupingFormId(#Param("groupingFormId") UUID groupingFormId);
}
Domain:TransitItemsMapping.java
#Data
#Entity
#Table(name = "TransitItemsMapping")
public class TransitItemsMapping implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "uuid", strategy = "uuid2")
#GeneratedValue(generator = "uuid")
#Column(name = "transit_Item_id",unique = true, nullable = false)
private UUID transitItemId;
#ToString.Exclude
#JsonManagedReference
#JsonIgnore
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "grouping_form_id")
//#OnDelete(action = OnDeleteAction.CASCADE)
private GroupingForm groupingForm;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(referencedColumnName = "dim_Item_ID",name = "item_id")
private Item item;
#Column(name ="item_relationship_id", insertable = false,updatable = false)
private String itemRelationshipId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "item_relationship_id",referencedColumnName = "dim_item_relationship_id")
private VendorFactoryItem vendorFactoryItem;
#Column(name = "edam_id")
private String edamId;
#Column(name = "model_number")
private String modelNumber;
#Column(name = "description")
private String description;
#Column(name = "packaging_details")
private String packagingDetails;
#Column(name = "packaging_method")
private String packagingMethod;
#Column(name = "is_side_stack")
private String isSideStack;
#Column(name = "quantity")
private Integer quantity;
#Column(name = "dimensions")
private String dimensions;
#Column(name = "product_net_weight")
private String productNetWeight;
#Column(name = "plastic_bag_ind")
private String plasticBagInd;
#Column(name = "insertion_order")
private Integer insertionOrder;
#Column(name = "comments")
private String comments;
#Column(name = "item_unique_id")
private String itemUniqueId;
#Column(name = "itm_pak_qty")
private Integer itemPackQuantity;
}
GroupingForm.java
#Setter
#Getter
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode
#Entity
#Table(name = "GroupingForm")
public class GroupingForm implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GenericGenerator(name = "uuid", strategy = "uuid2")
#GeneratedValue(generator = "uuid")
#Column(name = "grouping_form_id",unique = true, nullable = false)
private UUID groupingFormId;
#Column(name = "grouping_form_name")
private String groupingFormName;
#Column(name = "vid")
private String vid;
#Column(name = "vendor_name")
private String vendorName;
#Column(name = "hovbu")
private String hovbu;
#Column(name = "fid")
private String fid;
#Column(name = "factory_name")
private String factoryName;
#Column(name = "item_count")
private Integer itemCount;
#CreationTimestamp
#Column(name = "creation_date")
private Timestamp creationDate;
#Column(name = "created_by")
private String createdBy;
#UpdateTimestamp
#Column(name = "modified_date")
private Timestamp modifiedDate;
#Column(name = "modified_by")
private String modifiedBy;
#Column(name = "product_engineer")
private String productEngineer;
#Column(name = "status")
private String status;
#Column(name = "sourcing_type")
private String sourcingType;
#Column(name = "total_comments")
private Integer totalComments;
#Column(name = "factory_name_chinese")
private String factoryNameChinese;
#Column(name = "grouping_form_type")
private String groupingFormType;//to save as Product/transit/Product_transit
#Column(name = "ref_id")
private String refId;
#JsonBackReference
#OneToMany(mappedBy = "groupingForm", cascade = CascadeType.ALL)
private List<ProductItemsMapping> productItems = new ArrayList<>();
#JsonBackReference
#OneToMany(mappedBy = "groupingForm", cascade = CascadeType.ALL)
private List<TransitItemsMapping> transitItems = new ArrayList<>();
#Column(name = "pdf_status")
private String pdfStatus;
public GroupingForm(UUID groupingFormId,String groupingFormName, String vid, String vendorName, String hovbu,
String fid, String factoryName, String status, String sourcingType, Integer totalComments,
Date creationDate, String createdBy, Date modifiedDate, String modifiedBy, String productEngineer,
Integer itemCount, String groupingFormType, String refId, String factoryNameChinese) {
this.groupingFormId = groupingFormId;
this.groupingFormName = groupingFormName;
this.vid = vid;
this.vendorName = vendorName;
this.hovbu = hovbu;
this.fid = fid;
this.factoryName = factoryName;
this.status = status;
this.sourcingType = sourcingType;
this.totalComments = totalComments;
this.creationDate = creationDate!=null?new Timestamp(creationDate.getTime()):null;
this.createdBy = createdBy;
this.modifiedDate = modifiedDate!=null?new Timestamp(modifiedDate.getTime()):null;
this.modifiedBy = modifiedBy;
this.productEngineer = productEngineer;
this.itemCount = itemCount;
this.groupingFormType = groupingFormType;
this.refId = refId;
this.factoryNameChinese = factoryNameChinese;
}
}
Service: methods which already annotated with #Transactional
private void updateTransitItem(GroupingCardsDto groupingCardsDto, GroupingForm groupingForm) {
transitItemRepository.deleteByGroupingFormId(groupingCardsDto.getGroupingFormDto().getGroupingFormId());
groupingFormService.saveTransitItems(groupingCardsDto.getGroupingFormDto(), groupingForm);
}
when I am running eclipse in debug mode then my breakpoint is stuck in delete method. I am using
PostgreSQL 9.6.24 on x86_64-pc-linux-gnu, compiled by Debian clang version 12.0.1, 64-bit
version, and for pool connection Hikari-CP-3.2.0.
And If I let my debug running after long time (~45min) I am getting below error.
marked as broken because of SQLSTATE(08006), ErrorCode(0)\norg.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
Thanks in advance.
There are two possible reasons for this.
Either your delete statement actually takes a really long time, or it is stuck on a lock.
45 min, is certainly a lot for simple delete and could only be expected when you are working on huge amounts of data, like many millions of rows. Use the explain plan to validate that the expected indexes are used.
I consider locks the more likely reason for the problem. You'll need to check what locks are present and where they are coming from. This wiki page about lock monitoring in PostgreSQL seems to be a good starting point.

Spring Boot Data JPA detached entity passed to persist on #OneToMany and #OneToOne

Problem
I am trying to store an object in my Postgres database. This consists of the Order.class, (List) OrderDevice.class, and a Department.class.
The important thing is that the OrderDevices are always stored new in the DB, but a Department may already exist.
When I try to save the object to my database using save I get the following error message: (shown below)
I get the error message "detached entity passed to persist: com.niclas.model.OrderDevice" if the department does not exist yet, if the department exists the error message looks like this: "detached entity passed to persist: com.niclas.model.Department".
Solution attempts
This solution cannot be used because I do not use bidirectional mapping.
(I don't want to use a bidirectional mapping because I want to access the departments without an order.)
I also tried to change the Cascade types to MERGE like in this solution
I also tried using #Transactional on the method
I also tried to save the children in the database first and then the parent like this:
departmentRepository.save(order.getDepartment()); orderDeviceRepository.saveAll(order.getDevices()); orderRepository.save(order);
I hope I have described my good enough and I am happy about suggestions for solutions
Error.log
The log can be viewed here. (The formatting did not work here)
Order.class
#Entity
#Table(name = "orders")
public class Order extends AuditModel {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO) //TODO better config for GenerationType
private long id;
#Column(name = "order_id")
private String orderId;
#Column(name = "department_id")
private long departmentId;
#OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "department", referencedColumnName = "id")
private Department department;
#JsonProperty("deviceList")
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "order_id", referencedColumnName = "order_id")
private List<OrderDevice> devices;
#JsonProperty("forename")
#Column(name = "sender_forename")
private String senderForename;
#JsonProperty("surname")
#Column(name = "sender_surname")
private String senderSurname;
#Column(name = "notes", columnDefinition = "TEXT")
private String notes;
#Column(name = "month")
private int month;
#Column(name = "year")
private int year;
public Order() {
}
... Getter/Setters
}
OrderDevice.class
#Entity
#Table(name = "order_devices")
public class OrderDevice extends AuditModel{
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO) //TODO better config for GenerationType
private long id;
#Column( name = "order_id", insertable = false, updatable = false )
private String orderId;
#Column(name = "device_id")
private long deviceId;
#Column(name = "device_name")
private String deviceName;
#Column(name = "priceName")
private String priceName;
#Column(name = "price")
private double price;
#Column(name = "count")
private int count;
public OrderDevice() {
}
... Getters/Setters
}
Department.class
#Entity
#Table(name = "departments")
public class Department {
//TODO add Form Validation
//TODO better Naming for From Attributes on Frontend and Backend
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO) //TODO better config for GenerationType
private long id;
#Column(name = "department_name")
private String department;
#Column(name = "contact_person_forename")
private String forename;
#Column(name = "contact_person_surname")
private String surname;
#Column(name = "contact_person_mail")
private String mail;
#Column(name = "street")
private String street;
#Column(name = "house_number")
private String houseNumber;
#Column(name = "location")
private String location;
#Column(name = "postal_code")
private int postalCode;
#Column(name = "country")
private String country;
#Column(name = "auto_send_invoice")
private boolean autoSend;
#Column(name = "registered")
private boolean registered;
public Department() {
}
... Getter/Setters
}
OrderController.class
#Slf4j
#RestController
public class OrderController {
private final DepartmentRepository departmentRepository;
private final OrderRepository orderRepository;
private final OrderDeviceRepository orderDeviceRepository;
public OrderController(OrderRepository orderRepository, DepartmentRepository departmentRepository,
OrderDeviceRepository orderDeviceRepository) {
this.orderRepository = orderRepository;
this.departmentRepository = departmentRepository;
this.orderDeviceRepository = orderDeviceRepository;
}
#PostMapping("/orders/add")
public ResponseEntity<Order> addDepartment(#RequestBody Order order) throws JsonProcessingException {
order.setOrderId(order.generateOrderId());
DateTime dateTime = new DateTime();
order.setMonth(dateTime.getMonthOfYear());
order.setYear(dateTime.getYear());
order.getDevices().forEach(orderDevice -> {
orderDevice.setOrderId(order.getOrderId());
});
//departmentRepository.save(order.getDepartment());
//orderDeviceRepository.saveAll(order.getDevices());
orderRepository.save(order);
return new ResponseEntity<>(order, HttpStatus.CREATED);
}
Update
If the objects are created in this way, no error will occur and the order will be successfully saved in the database.
However, I don't understand why it works this way and not via ObjectMapper. Does anyone know why?
#PostMapping("/orders/add")
public ResponseEntity<Order> addDepartment(#RequestBody JsonNode jsonNode) throws JsonProcessingException {
Order order = new Order();
JsonNode departmentJson = jsonNode.get("department");
Department department;
if ( departmentJson.get("id").canConvertToInt() ) {
department = departmentRepository.findDepartmentById(departmentJson.get("id").asInt());
} else {
department = new Department();
department.setDepartment(departmentJson.get("department").asText());
department.setForename(departmentJson.get("forename").asText());
department.setSurname(departmentJson.get("surname").asText());
department.setMail(departmentJson.get("mail").asText());
department.setStreet(departmentJson.get("street").asText());
department.setHouseNumber(departmentJson.get("houseNumber").asText());
department.setLocation(departmentJson.get("location").asText());
department.setPostalCode(departmentJson.get("postalCode").asInt());
department.setCountry(departmentJson.get("country").asText());
department.setAutoSend(departmentJson.get("autoSend").asBoolean());
department.setRegistered(departmentJson.get("registered").asBoolean());
}
order.setDepartment(department);
order.setOrderId(order.generateOrderId());
order.setDepartmentId(department.getId());
List<OrderDevice> orderDevices = new ArrayList<>();
JsonNode devices = jsonNode.get("deviceList");
for (JsonNode node : devices) {
//TODO replace this mess with objectMapper
if (node.has("count") && node.get("count").asInt() != 0){
OrderDevice device = new OrderDevice();
device.setOrderId(order.getOrderId());
device.setDeviceId(node.get("id").asLong());
device.setDeviceName(node.get("deviceName").asText());
device.setPriceName(node.get("priceName").asText());
device.setPrice(node.get("price").asDouble());
device.setCount(node.get("count").asInt());
orderDevices.add(device);
}
}
order.setDevices(orderDevices);
order.setSenderForename(jsonNode.get("forename").asText());
order.setSenderSurname(jsonNode.get("surname").asText());
order.setNotes(jsonNode.get("notes").asText());
DateTime dateTime = new DateTime();
order.setMonth(dateTime.getMonthOfYear());
order.setYear(dateTime.getYear());
orderRepository.save(order);
return new ResponseEntity<>(order, HttpStatus.CREATED);
}
You can try to use instead of orderRepository.save(order) use orderRespostiory.saveOrUpdate(order).

how does lazy loading work

I have 2 classes.Video and VideoLinks.VideoLinks related to Video by ManyToOne and LazyLoading.Lazy loading means when i need Video then Video will be fetched.
i select VideoLinks and then sleep 10 seconds.i change Video title in database and after 10 seconds application prints related Video title.But this title is not changed title but old title.
Video:
#Entity
#Table(name = "video")
#XmlRootElement
public class Video implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "title")
private String title;
#Column(name = "url")
private String url;
#Lob
#Column(name = "description")
private String description;
#Column(name = "date")
#Temporal(TemporalType.TIMESTAMP)
private Date date;
#Column(name = "focused_word")
private String focusedWord;
#Column(name = "tags")
private String tags;
#Column(name = "seo_title")
private String seoTitle;
#Column(name = "seo_description")
private String seoDescription;
#Column(name = "category_id")
private String categoryId;
#Column(name = "slug")
private String slug;
#Column(name = "body")
private String body;
#Column(name = "thumb")
private String thumb;
#Column(name = "body_html")
private String bodyHtml;
public Video() {
}
public Video(Integer id) {
this.id = id;
}
//getter-setters
}
VideoLinks:
#Entity
#Table(name = "video_links")
#XmlRootElement
public class VideoLinks implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Column(name = "url")
private String url;
#Column(name = "text")
private String text;
#Basic(optional = false)
#Column(name = "working")
private boolean working;
#JoinColumn(name = "video_id", referencedColumnName = "id")
#ManyToOne(optional = false, fetch = FetchType.LAZY)
private Video videoId;
public VideoLinks() {
}
public VideoLinks(Integer id) {
this.id = id;
}
public VideoLinks(Integer id, boolean working) {
this.id = id;
this.working = working;
}
//getter-setters
}
Main:
public static void main(String[] args) {
VideoServiceInter serviceVideo = new VideoService();
VideoLinks videoLinks = serviceVideo.getVideoLinks(15);
System.out.println("i fetched VideoLinks but not Video yet");
try {
Thread.sleep(10000);//at this waiting time i change title in database
} catch (InterruptedException ex) {
LOG.log(Level.SEVERE, null, ex);
}
System.out.println(vl.getVideoId().getTitle());
}

how to resolve the 'save transient instance before saving' error on one to many relationship in hibernate jpa

this is the parent entity this is the child entityi have tried the suggested solution to similar error above but my application still spits out the same exception. please i need help
below is the exception
org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing: com.domkat.springmvcjpa.model.Cpfaceleft1angle.cpftid -> com.domkat.springmvcjpa.model.Fromtocp
at org.hibernate.engine.spi.CascadingAction$8.noCascade(CascadingAction.java:380)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:177)
at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:162)
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:153)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:89)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1234)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:515)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy626.save(Unknown Source)
#Entity
#Table(name = "cpobservedhorizontalangles")
public class Cpobservedhorizontalangles implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "degree")
private Integer degree;
#Column(name = "minute")
private Integer minute;
#Column(name = "second")
private Integer second;
#Column(name = "degminsec")
private String degminsec;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "ohaid")
private Integer ohaid;
#OneToMany(cascade={CascadeType.ALL},mappedBy = "ohaid")
private List<Cpfaceleft2angle> cpfaceleft2angleList;
#OneToMany(cascade={CascadeType.ALL},mappedBy = "ohaid")
private List<Cpfaceright2angle> cpfaceright2angleList;
#OneToMany(cascade={CascadeType.ALL},mappedBy = "ohaid")
private List<Cpfaceleft1angle> cpfaceleft1angleList;
#OneToMany(cascade={CascadeType.ALL},mappedBy = "ohaid")
private List<Cpfaceright1angle> cpfaceright1angleList;
...getters and setters... this is the child entity
#Entity
#Table(name = "cpfaceleft1angle")
public class Cpfaceleft1angle implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#OneToMany(cascade={CascadeType.PERSIST},mappedBy = "cpfl1id")
private List<Fromtocp> fromtocpList;
#JoinColumn(name = "ohaid", referencedColumnName = "ohaid")
#ManyToOne
private Cpobservedhorizontalangles ohaid;
#JoinColumn(name = "faceid", referencedColumnName = "faceid")
#ManyToOne
private Faceleft faceid;
...getters and setters... this is the parent class but it contains other
entities
public class Fromtocp implements Serializable {
private static final long serialVersionUID = 1L;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Column(name = "distance")
private Double distance;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "ftcpid")
private Integer ftcpid;
#Column(name = "diffleft")
private String diffleft;
#Column(name = "diffright")
private String diffright;
#Column(name = "meandiff")
private String meandiff;
#Column(name = "oadegdec")
private Double oadegdec;
#Column(name = "fb")
private Double fb;
#Column(name = "bb")
private Double bb;
#JoinColumn(name = "fromcp", referencedColumnName = "cpid")
#ManyToOne
private Controlpoints fromcp;
#JoinColumn(name = "cpfl1id", referencedColumnName = "id")
#ManyToOne
private Cpfaceleft1angle cpfl1id;
#JoinColumn(name = "cpfl2id", referencedColumnName = "id")
#ManyToOne
private Cpfaceleft2angle cpfl2id;
#JoinColumn(name = "cpfr1id", referencedColumnName = "id")
#ManyToOne
private Cpfaceright1angle cpfr1id;
#JoinColumn(name = "cpfr2id", referencedColumnName = "id")
#ManyToOne
private Cpfaceright2angle cpfr2id;
#JoinColumn(name = "tocp", referencedColumnName = "cpid")
#ManyToOne
private Controlpoints tocp;
...this is the other entity the parent class contains.
#Controller
public class SurveyController {
#Autowired
private SurveyService ss;
#Autowired
private ControlPointService cps;
#Autowired
private ScpService sps;
#Autowired
private CpobservedhorizontalanglesService cpos;
#Autowired
private Cpfaceleft1angleService cpfl1;
#Autowired
private Cpfaceleft2angleService cpfl2;
#Autowired
private Cpfaceright1angleService cpfr1;
#Autowired
private Cpfaceright2angleService cpfr2;
#Autowired
private FromTocpService ftcps;
#Autowired
private FaceleftService fls;
#Autowired
private FacerightService frs;
private Processor processor = new Processor();
HttpSession session;
#RequestMapping(value = "/surveydetails")
public String showSurveyDetailsPage(Model model) {
Surveys survey = new Surveys();
model.addAttribute("survey", survey);
return "SurveyDetails";
}
#RequestMapping(value = "/stations", method = RequestMethod.POST)
public String createSurvey(#RequestParam("surveyTitle") String title,
#RequestParam("cp1Label") String cp1Label, #RequestParam("cp1Northings") double northingsCp1,
#RequestParam("cp1Eastings") double eastingsCp1, #RequestParam("cp2Label") String cp2Label,
#RequestParam("cp2Northings") double northingsCp2, #RequestParam("cp2Eastings") double eastingsCp2,
#RequestParam("distance") double distance, #RequestParam("fl1Deg") int fl1Deg,
#RequestParam("fl1Min") int fl1Min, #RequestParam("fl1Sec") int fl1Sec,
#RequestParam("fl2Deg") int fl2Deg, #RequestParam("fl2Min") int fl2Min, #RequestParam("fl2Sec") int fl2Sec,
#RequestParam("fr1Deg") int fr1Deg, #RequestParam("fr1Min") int fr1Min, #RequestParam("fr1Sec") int fr1Sec,
#RequestParam("fr2Deg") int fr2Deg, #RequestParam("fr2Min") int fr2Min, #RequestParam("fr2Sec") int fr2Sec) {
Surveys survey = new Surveys();
Scp scp = new Scp();
Signups su = null;
Cpobservedhorizontalangles o1 = new Cpobservedhorizontalangles();
o1.setDegree(fl1Deg);
o1.setMinute(fl1Min);
o1.setSecond(fl1Sec);
o1.setDegminsec(processor.degToString(fl1Deg, fl1Min, fl1Sec));
Cpfaceleft1angle fl1 = new Cpfaceleft1angle();
fl1.setOhaid(o1);
fl1.setFaceid(faceleft1);
cpos.save(o1);
cpfl1.save(fl1);
please help. thanks
i have resolved the problem. And in addition i found out how i can actually save just the parent class by calling the save method on the parent and then it saves the child entities as well. jpa makes it quite easy.
i will use an illustration of employee and address. lets say an employee can have more than one address it means we will have two tables in the database and two entity classes, one for each of these tables right?. it also means that the employee table becomes the parent table while the address becomes the child table right? the code below just shows how you can save the parent class and by the saving the parent class the child entities get saved as well! all you do is set the parent object(in this case the employee) on the child object(in this case the address), then set the List(the list of child in this case is address. so it becomes List) on the parent entity. then call the save method on the parent.
...necessary imports...
#Entity
#Table(name = "address")
#NamedQueries({
#NamedQuery(name = "Address.findAll", query = "SELECT a FROM Address a")})
public class Address implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "address_id")
private Integer addressId;
#Column(name = "employee_address")
private String employeeAddress;
#JoinColumn(name = "employee_id", referencedColumnName = "employee_id")
#ManyToOne
private Employee employeeId;
public Address() {
}
...getters and setters for this entity...
#Entity
#Table(name = "employee")
#NamedQueries({
#NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e")})
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "employee_id")
private Integer employeeId;
#Column(name = "name")
private String name;
#Column(name = "email")
private String email;
#Column(name = "phone")
private String phone;
#OneToMany(cascade=CascadeType.ALL,mappedBy = "employeeId")
private List<Address> addressList;
public Employee() {
}
...getters and setters for this class...
...below is the class that makes use of the entities...
public class SaveExample {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPAJoinTableTutorialsPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Employee employee = new Employee();// employee object
Address address = new Address(); // Address Object
address.setEmployeeAddress("set the value");
address.setEmployeeId(employee);
List<Address>addressList=new ArrayList<>();
addressList.add(address);
employee.setEmail("set the value");
employee.setName("set the value for name");
employee.setPhone("set the value");
employee.setAddressList(addressList);
em.persist(employee);
em.getTransaction().commit();
}
}
i hope that helps some people..thanks

Categories