3

I am doing an application in play framework in which I need to store the same instance of a non-Entity object into a JPA Entity without persisting it into the database, I want to know if it's possible to achieve that or not using annotations. A sample code of what I am looking for is:

 public class anEntity extends Model {
    @ManyToOne
    public User user;

    @ManyToOne
    public Question question;


    //Encrypted candidate name for the answer
    @Column(columnDefinition = "text")
    public BigInteger candidateName;

    //I want that field not to be inserted into the database
    TestObject p= new TestObject();

I tried @Embedded annotation but its supposed to embed the object fields into the entity table. Is there anyway to use @Embedded while keeping the object column hidden in the entity table?

fasseg
  • 17,504
  • 8
  • 62
  • 73
dlock
  • 9,447
  • 9
  • 47
  • 67
  • i edited the question and answer a bit to clarify that always the same transient instance should be used. hope you dont mind.. – fasseg May 09 '11 at 20:02

1 Answers1

7

Check out the @Transient annotation:

"This annotation specifies that the property or field is not persistent. It is used to annotate a property or field of an entity class, mapped superclass, or embeddable class."

To make sure you always get the same object you can implement the Singleton pattern, so your entities can use its getInstance() method to set the transient object:

so this should do the trick:

public class anEntity extends Model {
    @Transient
    private TransientSingleton t;

    public anEntity(){ // JPA calls this so you can use the constructor to set the transient instance.
        super();
        t=TransientSingleton.getInstance();
    }


public class TransientSingleton { // simple unsecure singleton from wikipedia

    private static final TransientSingleton INSTANCE = new TransientSingleton();
    private TransientSingleton() {
        [...do stuff..]
    }
    public static TransientSingleton getInstance() {
        return INSTANCE;
    }
}
fasseg
  • 17,504
  • 8
  • 62
  • 73
  • I tried it but it gives me a null pointer exception when I try to use the transient object after fetching the entity from the database. – dlock May 09 '11 at 18:54
  • add a Constroctur to your class and set the Testobject there, as pointed out in the answer.. – fasseg May 09 '11 at 18:56
  • i'm quite sure that this is supposed to work, but you can also try setting the transient object in a simple block {} in your class: http://www.xs4all.nl/~kzeil/en/project/java/initializer-block.html – fasseg May 09 '11 at 19:03
  • also you have to use a default constructor. without any arguments. – fasseg May 09 '11 at 19:05
  • and dont confuse the `@Transient` annotation with the `transient` keyword. They're both valid on fields ;) http://www.javabeat.net/tips/168-what-is-transient-keyword-in-java.html – fasseg May 09 '11 at 19:09
  • I instantiated the object in a default constructor and now it doesnt throw any exceptions. But each time I call Entity.testObject it returns a new object. I need to have get the same object each time I call its getter from the entity. Any idea? – dlock May 09 '11 at 19:18
  • sure: you could use a setter to set the transient object after you fetched the entity. Then you can inject any instance you want. you wont need the `new TransientObject()` part in the Constructor though ;) – fasseg May 09 '11 at 19:26
  • I am not trying to Inject. To be more clear, I am trying to save an object into the entity that has some data that I use for encrypting the entity fields. Each time that encryption object is instantiated, it's initialized with different field values because it has a random factor. So I need the same object used to encrypt the entity fields in order to be able to decrypt that fields. At the same time, I don't want that object to be visible in the database so that the encryption key in the object remains confidential. Sorry for being so confusing, I am doing my best. Thanks for helping me btw :) – dlock May 09 '11 at 19:31
  • you can just **set the same encryption object** to every entity using it's setter. For the encryption object you probably want to implement a **Singleton** to make sure you are always getting the same instance. Then you can do something like `t=EncryptionObject.getInstance()` in your Constructor. Check here: http://en.wikipedia.org/wiki/Singleton_pattern – fasseg May 09 '11 at 19:35
  • That wont work either because every entity instance should have a unique encryption object to generate different hashes for the same field values. I am sorry for not being able to explain perfectly. – dlock May 09 '11 at 20:32
  • when you need the same object to encrypt as you used to decrypt for every single entity, and you persist the entites you will have to persist the object you use for encryption, but that would be a broken encryption scheme... – fasseg May 09 '11 at 20:41
  • It's working fine when I persist the encryption object with @Embedded annotation. I thought there is a solution to achieve the same without persisting the object. – dlock May 09 '11 at 21:06