Lazy Hibernate Initialization No Session, Could not initialize Proxy - spring

I am creating a e-prescribing module will allow several orders to be created and added to a list before being confirmed (saved in DB at once together). I have two forms - One where the order is created and the second with a link to add more orders, where the submit button will store all the orders (ArrayList items) in the DB. i.e. Each order upon creation gets added to an ArrayList [createNewDrugOrder() method below]
When I try to save each order inside this method - it works fine. but my requirement is to have the facility to store the orders as a draft before confirming them (storing in DB).
public class DrugordersPageController{
SessionFactory sessionfactory;
public void controller(){
if ("addDraftOrder".equals(action)){
createNewDrugOrder();
}
if ("confirmOrder".equals(action)){
saveOrder();
}
}
createNewDrugOrder(){
DrugOrder order = new DrugOrder();
order.setDose(1);
order.setDuration(1);
order.setQuantity(1);
ConfirmOrderClass.orderToConfirm.add(order);
}
saveOrder(){
DrugOrder order = ConfirmOrderClass.getDrugOrderMain();
order = (DrugOrder) Context.getOrderService().saveOrder(order, null); //Here is where error is thrown
}
}
class ConfirmOrderClass{
public static ArrayList<DrugOrder> orderToConfirm = new ArrayList<DrugOrder>();
public static ArrayList<DrugOrder> getDrugOrderMain(){
return orderToConfirm;
}
}
I understand this is a case of object being detached from the session, but I am unable to get it fixed. Calling session.save or session.update in the second form doesn't help..Neither does Hibernate.initialize(object) or adding a #Transactional notation
when I call Session s = sessionfactory.getCurrentSession or openSession, i still get null pointer error. Although I am able to retrieve the values of order.getDose(), order.getDuration() etc..
Please help!

Related

Spring update all entity with save

Good morning everyone,
I am trying to update an entity completely through its id, I am using a repository that extends from JPA, I think that just by making it save the system it would crush the old one but it is not like that, I am getting this error:
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
I have tried to use entityManager.flush (); but I get an error:
javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'flush' call
I have found options to update a database field but what I really want is to crush the database row completely, is it that complicated? How should I do it? Should I delete the record and recreate it? (I am not convinced because we are generating two transitions but I do not know if it is normal or not)
I put the code responsible for modifying the entity:
#PostMapping ("/ user")
public ResponseEntity postUser (#RequestBody User user) {
Map <Object, Object> model = new HashMap <> ();
entityManager.flush ();
User newUSer = userRepository.saveAndFlush (user);
model.put ("user", newUSer);
return ok (model);
}
Thank you!
Ok, after some test accounts I have found how to make it work correctly, I am doing something wrong, since when I make this code I get it correctly:
#PostMapping ("/ user")
public ResponseEntity postUser (#RequestBody User user) {
Map <Object, Object> model = new HashMap <> ();
AtomicReference <ResponseEntity> responseEntity = new AtomicReference <> ();
Optional <User> optionalUser = Optional.of (userRepository.findById (user.getId ()). Get ());
OptionalConsumer.of (optionalUser) .ifPresent (u -> {
u.setPassword (user.getPassword ());
userRepository.save (u);
model.put ("user", u);
responseEntity.set (ok (model));
}). ifNotPresent (() -> responseEntity.set (notFound (). build ()));
return responseEntity.get ();
}
So what I'm going to do is create a merge method in the User model to modify the data passed by parameter and save it correctly (I'm open to a better way, there may be more recommended ways to work, tell me please!)

ArrayListModel will not sync with JList

I have combed through SO, and have found many questions on the topic of my problem but do not answer it.
I am setting up an MVC, I have set up things correctly to best of my knowledge but I cannot get the Controller to show in my view. I am working on an assignment that essentially is a program for a Video Rental Store.
First, In a class called RentalStoreGUI, I set up my panels and everything looks good when I run.
RentalStoreEngine model = new RentalStoreEngine();
JList<DVD> list = new JList<DVD>();
list.setModel(model);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setVisible(true);
list.setSelectedIndex(0);
jScrollPane = new JScrollPane(list);
add(jScrollPane, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
As you can see I set my model for the list based on another class called RentalStoreEngine() and it implements AbstractListModel. The Abstract List model is functioning when I do class specific testing and all of the necessary methods are implemented. Here is an example of my add method from that class:
public void add(DVD d){
if (d != null){
rentals.add(d);//rentals is an arrayList<DVD> instantiated earlier
fireIntervalAdded(this, rentals.size() - 1, rentals.size() - 1);
}
}
Here is the actionPerformed method, it runs DVD_Dialog which simply gets some input from the user and creates a new DVD object from that.
public void actionPerformed(ActionEvent event) {
if(event.getSource() == rentDVD){
DVD_Dialog = new RentDVDDialog(this, null);
DVD_Dialog.clear();
DVD_Dialog.setVisible(true);
dvd = new DVD(DVD_Dialog.getTitleText(),DVD_Dialog.getRenterText(),
DVD_Dialog.getRentedOnText(), DVD_Dialog.getDueBackText());
if(DVD_Dialog.closeStatus() == true){
model.add(dvd);
}
}
Eclipse gives me no errors, until I run it. I then receive a nullPointerException at the line model.add(dvd); Based on all my research the list.setModel(model) and the fireIntervalAdded method line should update the Jlist on its own. But it does not. And as I said, class specific testing for both the GUI and the Model are producing the desired results, but when it comes to integrating them I am at a loss.

NHibernate IPreUpdateEventListener doesn't insert to second table

I'm prototyping some simple audit logging functionality. I have a mid sized entity model (~50 entities) and I'd like to implement audit logging on about 5 or 6. Ultimately I'd like to get this working on Inserts & Deletes as well, but for now I'm just focusing on the updates.
The problem is, when I do session.Save (or SaveOrUpdate) to my auditLog table from within the EventListener, the original object is persisted (updated) correctly, but my AuditLog object never gets inserted.
I think it's a problem with both the Pre and Post event listeners being called to late in the NHibernate save life cycle for the session to still be used.
//in my ISessionFactory Build method
nHibernateConfiguration.EventListeners.PreUpdateEventListeners =
new IPreUpdateEventListener[]{new AuditLogListener()};
//in my AuditLogListener
public class AuditLogListener : IPreUpdateEventListener
{
public bool OnPreUpdate(PreUpdateEvent #event)
{
string message = //code to look at #event.Entity & build message - this works
if (!string.IsNullOrEmpty(message))
AuditLogHelper.Log(message, #event.Session); //Session is an IEventSource
return false; //Don't veto the change
}
}
//In my helper
public static void Log(string message, IEventSource session)
{
var user = session.QueryOver<User>()
.Where(x => x.Name == "John")
.SingleOrDefault();
//have confirmed a valid user is found
var logItem = new AdministrationAuditLog
{
LogDate = DateTime.Now,
Message = message,
User = user
};
(session as ISession).SaveOrUpdate(logItem);
}
When it hits the session.SaveOrUpdate() in the last method, no errors occur. No exceptions are thrown. it seems to succeed and moves on. But nothing happens. The audit log entry never appears in the database.
The only way I've been able to get this to work it to create a completely new Session & Transaction inside this method, but this isn't really ideal, as the code proceeds back out of the listener method, hits the session.Transaction.Commit() in my main app, and if that transaction fails, then I've got an orphaned log message in my audit table for somethign that never happened.
Any pointers where I might be going wrong ?
EDIT
I've also tried to SaveOrUpdate the LogItem using a child session from the events based on some comments in this thread. http://ayende.com/blog/3987/nhibernate-ipreupdateeventlistener-ipreinserteventlistener
var childSession = session.GetSession(EntityMode.Poco);
var logItem = new AdministrationAuditLog
{
LogDate = DateTime.Now,
Message = message,
User = databaseLogin.User
};
childSession.SaveOrUpdate(logItem);
Still nothing appears in my Log table in the db. No errors or exceptions.
You need to create a child session, currentSession.GetSession(EntityMode.Poco), in your OnPreUpdate method and use this in your log method. Depending on your flushmode setting, you might need to flush the child session as well.
Also, any particular reason you want to roll out your own solution? FYI, NHibernate Envers is now a pretty mature library.

Getting DataContext error while saving form

I get this error when opening one specific form. The rest is working fine and I have no clue why this one isn't.
Error: An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported.
I get the error at _oDBConnection when I try to save. When I watch _oDBConnection while running through the code, it does not exist. Even when I open the main-window it does not exist. So this form is where the DataContext is built for the very first time.
Every class inherits from clsBase where the DataContext is built.
My collegue is the professional one who built it all. I am just expanding and using it (learned it by doing it). But now I'm stuck and he is on holiday. So keep it simple :-)
What can it be?
clsPermanency
namespace Reservation
{
class clsPermanency : clsBase
{
private tblPermanency _oPermanency;
public tblPermanency PermanencyData
{
get { return _oPermanency; }
set { _oPermanency = value; }
}
public clsPermanency()
: base()
{
_oPermanency = new tblPermanency();
}
public clsPermanency(int iID)
: this()
{
_oPermanency = (from oPermanencyData in _oDBConnection.tblPermanencies
where oPermanencyData.ID == iID
select oPermanencyData).First();
if (_oPermanency == null)
throw new Exception("Permanentie niet gevonden");
}
public void save()
{
if (_oPermanency.ID == 0)
{
_oDBConnection.tblPermanencies.InsertOnSubmit(_oPermanency);
}
_oDBConnection.SubmitChanges();
}
}
}
clsBase
public class clsBase
{
protected DBReservationDataContext _oDBConnection;
protected int _iID;
public int ID
{
get { return _iID; }
}
public DBReservationDataContext DBConnection
{
get { return _oDBConnection; }
}
public clsBase()
{
_oDBConnection = new DBReservationDataContext();
}
}
Not a direct answer, but this is really bad design, sorry.
Issues:
One context instance per class instance. Pretty incredible. How are you going to manage units of work and transactions? And what about memory consumption and performance?
Indirection: every entity instance (prefixed o) is wrapped in a cls class. What a hassle to make classes cooperate, if necessary, or to access their properties.
DRY: far from it. Does each clsBase derivative have the same methods as clsPermanency?
Constructors: you always have to call the base constructor. The constructor with int iID always causes a redundant new object to be created, which will certainly be a noticeable performance hit when dealing with larger numbers. A minor change in constructor logic may cause the sequence of constructor invocations to change. (Nested and inherited constructors are always tricky).
Exception handling: you need a try-catch everywhere where classes are created. (BTW: First() will throw its own exception if the record is not there).
Finally, not a real issue, but class and variable name prefixes are sooo 19xx.
What to do?
I don't think you can change your colleague's design in his absence. But I'd really talk to him about it in due time. Just study some linq-to-sql examples out there to pick up some regular patterns.
The exception indicates that somewhere between fetching the _oPermanency instance (in the Id-d constructor) and saving it a new _oDBConnection is created. The code as shown does not reveal how this could happen, but I assume there is more code than this. When you debug and check GetHashCode() of _oDBConnection instances you should be able to find where it happens.

Jpa testing and automatic rollback with Spring

I am in reference to Spring Roo In Action (book from Manning). Somewhere in the book it says "Roo marks the test class as #Transactional so that the unit tests automatically roll back any change.
Here is the illustrating method:
#Test
#Transactional
public void addAndFetchCourseViaRepo() {
Course c = new Course();
c.setCourseType(CourseTypeEnum.CONTINUING_EDUCATION);
c.setName("Stand-up Comedy");
c.setDescription(
"You'll laugh, you'll cry, it will become a part of you.");
c.setMaxiumumCapacity(10);
c.persist();
c.flush();
c.clear();
Assert.assertNotNull(c.getId());
Course c2 = Course.findCourse(c.getId());
Assert.assertNotNull(c2);
Assert.assertEquals(c.getName(), c2.getName());
Assert.assertEquals(c2.getDescription(), c.getDescription());
Assert.assertEquals(
c.getMaxiumumCapacity(), c2.getMaxiumumCapacity());
Assert.assertEquals(c.getCourseType(), c2.getCourseType());
}
However, I don't understand why changes in this method would be automatically rolled back if no RuntimeException occurs...
Quote from documentation:
By default, the framework will create and roll back a transaction for each test. You simply write code that can assume the existence of a transaction. [...] In addition, if test methods delete the contents of selected tables while running within a transaction, the transaction will roll back by default, and the database will return to its state prior to execution of the test. Transactional support is provided to your test class via a PlatformTransactionManager bean defined in the test's application context.
So, in other words, SpringJUnit4ClassRunner who runs your tests always do transaction rollback after test execution.
I'm trying to find a method that allows me to do a rollback when one of the elements of a list fails for a reason within the business rules established (ie: when throw my customize exception)
Example, (the idea is not recording anything if one element in list fails)
public class ControlSaveElement {
public void saveRecords(List<MyRecord> listRecords) {
Boolean status = true;
foreach(MyRecord element: listRecords) {
// Here is business rules
if(element.getStatus() == false) {
// something
status = false;
}
element.persist();
}
if(status == false) {
// I need to do roll back from all elements persisted before
}
}
...
}
Any idea? I'm working with Roo 1.2.2..

Resources