Unsaved Transient Instance Hibernate - excel

Although there are several questions related to this exception, Folks, this is not a possible duplicate . Iterating through multiple excel sheets using APACHE POI , I have to use JPA to perform a many to one relation
for (int i = 0; i < wb.getNumberOfSheets(); i++) {
HSSFSheet sheet = wb.getSheetAt(i);
....
if(i=0)
{
Baseclass obj = new Baseclass ();
obj.setname("name");
session.save(obj)
session.getTransaction().commit();
}
if(i=3)
{
Foreigclass obj2 = new Foreigclass ();
obj2.setsection("2A");
Baseclass obj = new Baseclass ();
--> obj2.setTransport(obj); // linking foreign keys // error comes here
session.save(obj2)
}
At the marked line, I am getting the following exception:
Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: model.CepTransport
at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:294)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:537)
at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:311)
at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:321)
at org.hibernate.type.TypeHelper.findDirty(TypeHelper.java:294)
at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:4243)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:546)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:232)
Can someone suggest what is wrong here ? The CASCADing properties are fine and everything works fine if data comes from only one excel sheet.

In below code you are creating objects for Foreigclass & Baseclass and trying to save only one:
Foreigclass obj2 = new Foreigclass (); // Created Foreigclass object
obj2.setsection("2A");
Baseclass obj = new Baseclass (); // Created Baseclass object
obj2.setTransport(obj); // linking foreign keys // error comes here
session.save(obj2);
So initially the obj2 and obj are in Transient state, so when you call session.save(obj2) it checks the linked entities and there state before making obj2 to Persistent state. As obj is still in Transient state it complains with error as:
org.hibernate.TransientObjectException: object references an unsaved transient instance
- save the transient instance before flushing: model.CepTransport.
Here I guess CepTransport is same as Baseclass.
To fix this issue, save your Baseclass before saving Foreigclass like this:
session.save(obj);
session.save(obj2);
But if you want to use CASCADE setting then check the settings at Foreigclass and make sure that the CASCADE values are correct.

Related

Object reference not set to an instance of an object - Multiple Projects (MVC)

I am working with the Contoso University tutorial and was trying it with both a modular attempt (separate projects for Models, DAL and WebUI - top picture in the attached picture) and a single project (containing all layers - bottom picture). In both cases the solution compiles without errors. However when I go to the details section for a student in web browser the modular project throws an error when I go to the second break point, starting:
Exception Details:
System.NullReferenceException: Object reference not set to an instance of an object.
The same model is passed into the view for each project,
#model ContosoUniversity.Models.Student
And a null reference exception occurs after the line:
#foreach (var item in Model.Enrollments){
I thought it may have been a namespace conflict between the ContosoUniversity.Models project and the Models folder in the ContosoUniversity project, however renaming the folder doesn't resolve this. Is there something else related to multiple projects that would cause a null value (Enrollments.cs not being sent to the model) to be encountered here, but not for a single project?
If its something deeper in the code I can follow up with full view-code and model classes.
Screenshot of working and non working solutions in VS2015Community
Since this is such a commonly confusing error to new developers, I've authored a post on my blog to explain what the error means in detail and how to debug it. TL;DR: Object reference not set to an instance of an object is a runtime error (hence why your project compiles fine) that occurs when you're expecting a variable to be an instance of a particular class, but it actually resolves to null at runtime.
This commonly occurs when you're selecting an object from a database, but nothing matches, or you've neglected to initialize a property on your model that requires initialization, like a list. Based on the line of code you've posted, my guess is that either the model itself is null (perhaps because it's coming from the database and you're not checking for null before sending it to the view), or the Enrollments property is null because you've neglected to initialize it, or it's not marked as virtual if your model is an instance of an entity class.
Whenever you request a specific object from the database, you should always check for null and handle appropriately. For example, if you're working on a "detail" action, your code should look something like:
public ActionResult Detail(int id)
{
var foo = db.Foos.Find(id); // potentially null, if no matching id
if (foo == null)
{
return new HttpNotFoundResult();
}
return View(foo);
}
If you have a list-style property on your model, you should always initialize it via the class constructor or a custom getter:
public class Foo
{
public Foo()
{
Bars = new List<Bar>();
}
public List<Bar> Bars { get; set; }
}
Or
public class Foo
{
private List<Bar> bars;
public List<Bar> Bars
{
get
{
if (bars == null)
{
bars = new List<Bar>();
}
return bars;
}
set { bars = value; }
}
}
If you're utilizing C# 6, the last one can be simplified to:
public class Foo
{
public List<Bar> Bars { get; set; } = new List<Bars>();
}
Finally, this is not necessary if you're dealing with an Entity Framework POCO, as long as the property is virtual:
public virtual ICollection<Bar> Bars { get; set; }
As part of the lazy-loading facility, Entity Framework automatically overrides the property such that it will never be null, only an empty collection if there's truly nothing there. However, if you neglect the virtual keyword, EF cannot do the necessary override to handle this.
Long and short, you need to figure out what variable is null that you're expecting to have an actual value, and then either do proper null-checking (which is a good idea regardless) or figure out why it's null instead of the value you expect.

Building a NSManagedObjectModel from several models

There are several reasons why somebody wants to merge multiple NSManagedObjectModel's. If you search the web, all responses are that it is not possible or that it is only possible for two unrelated entities that share one or more relationships. See this and this link for example.
However with a bit or more work it is (I think) possible to merge NSManagedObjectModels, even if the entities are related (as in parent-child) or if the attributes are spread out across multiple models.
Though it will not show as readily in the Xcode model editor and out-of-box transitions (probably) won't work.
In the answer below my observations about core data and my code on merging several models. If you find any bugs or have suggestions for improvements, please respond here.
Some things I noticed:
Copying a NSPropertyDescription (attribute, relationship) copies all its values, but not the entity to which it belongs. Same for the destinationEntity and inverseRelationship.
Thus a copied NSPropertyDescription should be added to an entity. As a result, all the children entities of that entity automatically get the property as well.
Copying a NSEntityDescription does not include the parent entity. So the tree (of NSManagedObjectEntity) has to rebuild manually.
If you set the parent of an entity, that (child) entity will immediately and automatically inherit all its parent properties. In other words when you ask an entity for its attributes, this entity already knows about all its attributes. It will not first query its parent. (reasonable assumption)
Adding entities to a model fills in the destination entities and inverse relationship descriptions of the relationsDescriptions of the added entities.
if you do not set the name of any entity or property before using it, core data will complain. That is the copy by name instead of value aspect.
Adding a property to an entity which already has a property with the same name (either from itself or inherited from its ancestor) will make core data complain.
This translates into the following code:
extension NSPropertyDescription
{
var isPlaceholder : Bool { return self.userInfo?["isPlaceholder"] != nil }
}
extension NSEntityDescription
{
var isPlaceholder : Bool { return self.userInfo?["isPlaceholder"] != nil }
}
func mergeModels(models: [NSManagedObjectModel]) -> NSManagedObjectModel?
{
var entities : [String : NSEntityDescription] = [:]
//support functions
let makeEntity : String -> NSEntityDescription = { entityName in
let newEntity = NSEntityDescription()
entities[entityName] = newEntity
newEntity.name = entityName
return newEntity
}
let setParent : (String, NSEntityDescription) -> () = { parentName, child in
if let parent = entities[parentName]
{
parent.subentities.append(child)
}
else //parent has not yet been encountered, so generate it
{
let newParentEntity = makeEntity(parentName)
newParentEntity.subentities.append(child)
}
}
//rebuild model: generate new description for each entity and add non-placeholder properties
for model in models
{
for entity in model.entities
{
guard let entityName = entity.name else { fatalError() }
let mergedEntity = entities[entityName] ?? makeEntity(entityName)
//set entity properties
if !entity.isPlaceholder
{
mergedEntity.abstract = entity.abstract
mergedEntity.managedObjectClassName = entity.managedObjectClassName
}
//set parent, if any
if mergedEntity.superentity == nil, //no parent set
let parentName = entity.superentity?.name //but parent is required
{
setParent(parentName, mergedEntity)
}
//set properties
for property in entity.properties
{
if property.isPlaceholder ||
mergedEntity.properties.contains({$0.name == property.name})
{ continue }
let newProperty = property.copy() as! NSPropertyDescription
mergedEntity.properties.append(newProperty)
}
}
}
//generate final model
let mergedModel = NSManagedObjectModel()
mergedModel.entities = Array(entities.values) //sets the destination entity and inverse relationship descriptions
return mergedModel
}
In the managedObjectModel (xcode editor) set the "placeholder" flag in the user info dictionary of the entity and/or the property.
The model generation can be refined by setting additional keys in the user info dictionary to specify which model has the prime entity/attribute/relationship (settings) and appropriately adjusting this code fragment.
However, if you can avoid using multiple models then avoid it. Your life will be much simpler by sticking to the standard single Model approach.
[Disclaimer: as far as I can tell, this code should work. No guarantees though.]
The NSManagedObjectModel class has the following factory methods / constructors
class func mergedModel(from: [Bundle]?)
class func mergedModel(from: [Bundle]?, forStoreMetadata: [String : Any])
init?(byMerging: [NSManagedObjectModel]?)
init?(byMerging: [NSManagedObjectModel], forStoreMetadata: [String : Any])
The optional forStoreMetadata attribute allows to specify the models' version.
see https://developer.apple.com/documentation/coredata/nsmanagedobjectmodel
(I suspect these methods not being available at the time the op asked & answered the question.)

QML memory management

I'm trying to test QML to understand how it works with C++. I have ClassA and ClassB - 2 similar C++ classes. Here is a ClassA. All methods are self explanatory with their names, so I won't place implementation here.
class ClassB;
class ClassA : public QObject
{
Q_OBJECT
public:
explicit ClassA(QObject *parent = 0);
~ClassA();
Q_PROPERTY(ClassB* classB READ getClassB WRITE setClassB NOTIFY classBChanged)
ClassB* getClassB() const;
void setClassB(ClassB *classB);
signals:
void classBChanged();
private:
ClassB *m_classB;
};
ClassB is the same, just change all *lassA* to *lassB* and all *lassB* to *lassA*.
Then I register both classed in QML with
qmlRegisterType<ClassA>("testmodule.test",1,0,"ClassA");
qmlRegisterType<ClassB>("testmodule.test",1,0,"ClassB");
And in QML code on mouse click I create both objects like this:
onClicked: {
var comp = Qt.createComponent("TClassA.qml"); //TClassA.qml is
//a component of type
//ClassA
var ca = comp.createObject();
comp = Qt.createComponent("TClassB.qml");
var cb = comp.createObject();
ca.classB = cb;
cb.classA = ca;
parent.blockFromGC = ca;
}
And after that I call garbage collector with gc(). I expected that ca is blocked from removal with parent.blockFromGC and cb is blocked from removal with reference from ca. But garbage collector destroyed cb and after that parent.blockFromGC.classB === null.
So I have second MouseArea with this code:
onClicked: {
console.log(mouse.button)
// if (mouse.button == Qt.RightButton) {
// console.log(parent.vasya.classB)
// }
gc();
console.log(parent.blockFromGC.classB) //I use cb here
}
So when I click the MouseArea I get in console:
qml: 1 //Left button
qml: null //value of parent.blockFromGC.classB
classB destroyed: TQMLClassB(0x34960d0) //I have qDebug() in destructor
So my object cb was destroyed.
So I have this questions:
1) Is there a way how I can register a C++ type as basic type, so I could
write var ca = new ClassA() instead of creating a *.qml file, creating a component and finally creating an object?
2) Why did garbage collector destroyed my cb object and what should I do
to keep this object from deleting?
Moreover! If I uncomment those commented lines
// if (mouse.button == Qt.RightButton) {
// console.log(parent.vasya.classB)
// }
regardless the button I press, the object is not destroyed anymore.
qml: 1 //left button
qml: TQMLClassB(0x3df8e90) //object is alive
.....
qml: 2 //right button
qml: TQMLClassB(0x3df8e90) //before gc() - alive
qml: TQMLClassB(0x3df8e90) //after gc() - alive
3) Where can I read about QML memory management in detailes? I find this behaviour really strange..
Addition 1: I played with this situation a bit more and the results were unpredictable. I updated from 5.3 to Qt 5.4 and this behavior with object deletion has gone. The problem is that the behavior was so unpredictable, that the fact I can't reproduce this behavior in Qt 5.4 doesn't mean that the problem is fixed. I'll try to look in bug reports and bug fixes. If I found something, I'll post it here. If not, I'll try to reproduce this situation in Qt 5.4 and post a report.
Like any QML type, you can define a component statically within another:
Component {
id: classAComponent
ClassA { }
}
onClicked {
var ca = classAComponent.createObject()
}
There is a subtlety here: assigning a QML object to a QML property will increase its JavaScript ref-count. But an instance stored only in the Q_PROPERTY of a C++ object won't be marked by the garbage collector.
QML has a dual ownership system. First it defines a hierarchy of QObject/QQuickItem used for display and ownership. Attached to this backbone is a garbage collection system where any QML object can own a tree of JavaScript objects through property var.
So to keep your ClassB object alive, you either have to keep it in a QML property, or provide a parent for it when calling component.createObject() (it's a hard ownership; it will be destroyed regardless of any JS reference to it when the parent is destroyed)
Example with the QML property:
Component {
id: classAComponent
ClassA {
property Item refClassB
}
}
onClicked {
var ca = classAComponent.createObject()
ca.refClassB = classBComponent.createObject()
}
Ideally you should avoid dynamically creating object as much as possible and use your C++ objects statically like normal QML components and let the declarative structure maintain the QObject backbone automatically, like this:
ClassA {
classB: ClassB { }
}
Sadly not so much, the best I know of, more for QML than C++ is Dynamic QML Object Creation from JavaScript.

How to restore metaclass on object to original class definition

I've been trying to create a TEMPORARY override on new objects, and then to remove the override on the objects themselves. I'm not sure if this can be done, but here is what I've tried so far.
// Say I have a class like:
class Validator {
boolean validate() { println "code here to return actual true/false"; false }
}
// I have two integration points one of them is Here before construction:
// First integration point:
// Save actual validate function
def realValidate = Validator.&validate
// Make new instances of Validator have the validate function hardwired to true
Validator.metaClass.validate { -> println "hardwired true"; true }
// Code I'd rather not modify
// Now some code executes which news up an instance and calls validate
def validator = new Validator()
validator.validate() // This correctly calls our override
// Second integration point.
// Without newing up a new Validator object, I'd like to remove the override.
Validator.metaClass = null
validator.metaClass.validate = Validator.&validate
// This throws "java.lang.IllegalArgumentException: object is not an instance of declaring class"
//validator.validate()
// So maybe I have to explicitly say:
realValidate.resolveStrategy = Closure.DELEGATE_FIRST
// But this still throws the same exception
//validator.validate()
// Perhaps if I tell my objects metaclass to forget about validate, it will bubble up and look for the method on its declaring class?
validator.metaClass.validate = { -> throw new MissingMethodException("validate", Validator.class, (Object[])[], false) }
// This throws MissingMethodException: No signature of method: Validator.validate() is applicable for argument types: () values: []
// Possible solutions: validate(), wait()
//validator.validate()
Apologies for not having a super specific question, since I don't know what all is possible in this particular area. I'd love both the reason why my code doesn't work, as well as alternatives to make it work.
This could be a per instance meta class problem... Validator.metaClass = null will set the global meta class for the Validator class to default. but your validator instance here is a Groovy class and thus stores a separate reference to the meta class in the instance itself. Calls with that instance will not go through a lookup of the global meta class and instead use the per instance meta class (the reference stored in the instance itself). Thus validator.metaClass = null is the only way to reset this
A small modification to your strategy would be fruitful. Use metaClass on the object instead of the Class.
// Say I have a class like:
class Validator {
boolean validate() { println "code here to return actual true/false"; false }
}
def validator = new Validator()
// mark that the pointer is on object instead of class
def realValidate = validator.&validate
validator.metaClass.validate { -> println "hardwired true"; true }
validator.validate() // This correctly calls our override
// Second integration point.
// DO NOT NEED THIS
// validator.metaClass = null
// Assign the method pointer to validate to call original validate
validator.metaClass.validate = realValidate
validator.validate()
Your approach did not work because you had validate() overridden on the metaClass of Class reference instead of the object itself.

Concurrent collection

I have a bunch of threads, each which create a lot of objects. As each object is created I need to check a collection of existing objects to make sure make sure an equal object hasn't already been created by another thread. If an equal object hasn't already been created then I need to add the object that was just created to the list of existing objects. So basically I need a mutex on a list.
I was thinking of doing something like this, but I don't know if there is a better way to do it in Groovy:
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
class FooService {
private final ReentrantLock lock = new ReentrantLock()
private def existingObjectList = []
def longRunningProcess(params) {
// create a bunch of threads that will all use someMethod
}
private def someMethod(def propertiesMap) {
def obj = new Foo(propertiesMap) // create an object
lock.lock() // lock the existing object list
try {
if(!existingObjectList.contains(obj)) {
existingObjectList.add(obj)
}
} finally {
lock.unlock() // unlock the existing object list
}
}
}
P.S. I don't think it will matter but this code is in a Grails service and I'm using the Grails Executor plugin to create the threads.

Resources