Annotation for mapping Joda Time "Period" in JPA using Eclipse Link - java

I am having a field - expiryLimit in my Item entity for which I thought of using joda-time Period which would be an appropriate type to use here.
Just to explain - expiryLimit is the number of year, month, days, or any duration after which a particular item will expire and using which I can calculate the exact expiryDate of an Item given a deliveryDate.
Now the problem I'm facing is finding an appropriate way to map this type into JPA.
Is there any available API or 3rd party library which provides some annotation to do that? Also I've used the Eclipse Link #Converter annotation to map DateTime with MySQL TimeStamp. So, would I need to do the same thing with Period also. And if yes, then to what type should I convert it. To varchar? or to Long? or some other type appropriate to represent a Period.

Ok, finally I've solved the issue by using EclipseLink #Converter only. This is how I've done it. I also welcome any comments on this way: -
ItemMaster entity: -
public class ItemMaster {
#Converter(
name="periodConverter",
converterClass = com.joda.converter.PeriodConverter.class
)
#Convert("periodConverter")
#Column(name = "expiry_limit", length = 2000)
private Period expiryLimit;
/** Constructors **/
public Period getExpiryLimit() {
return expiryLimit;
}
public void setExpiryLimit(Period expiryLimit) {
this.expiryLimit = expiryLimit;
}
}
PeriodConverter.class: -
public class PeriodConverter implements Converter {
private Logger log;
private static final long serialVersionUID = 1L;
#Override
public Object convertDataValueToObjectValue(Object str, Session session) {
if (str == null) {
log.info("convertDataValueToObjectValue returning null");
return null;
}
return new Period(str);
}
#Override
public Object convertObjectValueToDataValue(Object period, Session session) {
/** str format should be: - `PyYmMwWdDThHmMsS` **/
if (period == null) {
log.info("convertObjectValueToDataValue returning null");
return null;
}
return period.toString();
}
#Override
public void initialize(DatabaseMapping mapping, Session session) {
log = Logger.getLogger("com.joda.converter.PeriodConverter");
((AbstractDirectMapping) mapping).setFieldType(java.sql.Types.VARCHAR);
}
#Override
public boolean isMutable() {
return true;
}
}

Related

Silly Question about a validation case in Java and temporary variables

How does one set a temporary variable of date before it is updated? I would like to compare my initial date before it is updated.
Update: More code
* #hibernate.class table="t3sstations"
* #hibernate.join name="rgnjoin" table="stnregions" optional="true"
* #hibernate.join-key column="idstn"
*/
public class Station extends BaseSiteChildCFKObject implements Convertible, Comparable<Station> {
private static final long serialVersionUID = -2056063261398467275L;
protected final Log log = LogFactory.getLog(getClass());
private Project stationProject;
private Date project_startdate;
private Date date_initial;
Table it grabs from SQL using hibernate. It grabs the project's date from the column project_startdate. I want to compare the date that it is initially with the new/updated date. It updates the same value throughout the class.
/**
* #return
* #hibernate.many-to-one column="idproject" not-null="false"
* class="org.unavco.pbo.mdm.model.Project"
*/
#Required
public Project getStationProject() {
return stationProject;
}
public void setStationProject(Project stationProject) {
this.stationProject = stationProject;
}
/**
* #return
* #hibernate.property column="project_startdate"
*/
public Date getProject_startdate() {
return project_startdate;
}
public void setProject_startdate(Date project_startdate) {
this.project_startdate = project_startdate;
}
#AssertTrue
private boolean validateProjectDate() {
project_initialdate = new Date(project_startdate);
if (project_startdate.before(this.project_initialdate)){
return false;
}
if (project_startdate.before(this.stationProject.getStart_date())) {
return false;
}
if (this.stationProject.getEnd_date() != null) {
if (this.project_startdate.after(this.stationProject.getEnd_date())) {
return false;
}
}
return true;
}
So I don't think I found a temporary value holder but I did define the initial date as another variable inside the initializer. By placing it here, I save the date before it is changed and updated via hibernate.
public Station() {
super();
Date date_initial = this.project_startdate;
}
At the top of the class called Station. From there I also defined the getter and setter for date initial.
public Date getDate_initial(){
return date_initial;
}
public void setDate_initial(Date date_initial) {
this.date_initial = date_initial;
}
From there it accurately compares the initial date to the updated date. If it is safe then it continues to save. Otherwise it displays an error message to the user.

Using the Check class, add the code to have the Checks sorted by checkNumber

Using the Check class, add the code to have the Checks sorted by checkNumber.
import java.util.Date;
public class Check implements Comparable {
private int checkNumber;
private String payTo;
private Date date;
private float amount;
public int compareTo(Object arg0) {
//Insert code here
}
public int getCheckNumber() {
return checkNumber;
}
public void setCheckNumber(int checkNumber) {
this.checkNumber = checkNumber;
}
public String getPayTo() {
return payTo;
}
public void setPayTo (String payTo) {
this.payTo = payTo;
}
public Date getDate() {
return date;
}
public void setDate (Date date) {
this.date = date;
}
public float getAmount() {
return amount;
}
public void setAmount (float amount) {
this.amount = amount;
}
}
My solution is below, but it does not seem to work.
Can anyone help me with the solution?
public int compareTo(Object arg0) {
if(this.checkNumber == arg0.checkNumber)
return 0;
else
return this.checkNumber > arg0.checkNumber ? 1 : -1;
}
You didn't specify what you mean by "doesn't work", but reading your code, I'm assuming you get a compilation error.
The reason for this is because the code you were given has not specified a type for the comparable, so it doesn't know what type you even want to compare it to. It will use Object by default, which does not (by design) know a thing about Check's fields and methods.
The following modification is the best solution:
public class Check implements Comparable<Check> {
public int compareTo(Check arg0) {/* ...*/ }
}
This will force you to compare this to other Check's only and make arg0 a Check object, rendering its fields and methods available to you.
Should the parameters of the problem you were given not allow you to modify the provided code, then the (very very distant) second best solution is:
public int compareTo(Object arg0) {
Check other = null;
if(arg0 instanceof Check)
other = (Check)arg0;
// Other checks.
}
This adaptation would technically work for your problem given the stipulation that you are not allowed to modify the provided code, but is otherwise not at all recommended, as the contract for Comparable wants the type of object you wish to compare against to be specified, and not specifying it can introduce problems.
In fact, I'd say you are fully allowed to tell the person who gave you this problem that they are a terrible person for giving you a problem with this mistake in it, because not specifying a Comparable type is a really bad practice. Especially if they're teaching you how to program.

Spring batch, logging Skipped records / lines

In order to be able to log all skipped record / lines (from Flat file), I have linked Item (Data model) to FieldSet.getValues() in FieldSetMapper<T> implementation.
Here record is my Data model.
public void loadRecord(FieldSet fieldSet){
record.setFieldSet(fieldSet.getValues());
}
SB provides record/line for onSkipInRead in the FlatFileParseException. To have the same for onSkipInWrite and onSkipInProcess, I came up with the above solution.
Also, record does not store all the fields from the flat file, hence I can't each line using just the Data model.
Is this a good way to acheive this ?
Are there any other ways to do this ?
Is the record / line corresponding to an Item stored in any context ?
Thanks for the help !
Now I understand better your problem :)
Save the whole line into your domain object and not the FieldSet using a custom LineMapper.From LineMapper javadoc:
Interface for mapping lines (strings) to domain objects typically used
to map lines read from a file to domain objects on a per line basis.
Implementations of this interface perform the actual work of parsing a
line without having to deal with how the line was obtained.
So with a delegate is pretty easy solve your problem:
class StoreLineLineMapper implements LineMapper<DomainObject> {
private LineMapper<DomainObject> delegate;
public DomainObject mapLine(java.lang.String line, int lineNumber) throws java.lang.Exception {
DomainObject record = delegate.mapLine(line, lineNumber);
record.setLineInfo(new LineInfo(line, lineNumber));
return record;
}
}
The complete code for this use case:
public class UserMapper implements FieldSetMapper<User> {
#Override
public User mapFieldSet(FieldSet fieldSet) throws BindException {
User user = new User();
String ped = fieldSet.readString("Position effective date");
user.setId(fieldSet.readInt("User ID"));
user.setFn(fieldSet.readString("First Name"));
user.loadRecord(fieldSet); // store fieldSet for regenerating line in future
return user;
}
}
This will regenerate line from fieldSet (Delimiter is TAB):
class User{
#Override
public String toString() {
return StringUtils.arrayToDelimitedString(fieldSet,
DelimitedLineTokenizer.DELIMITER_TAB);
}
}
Log lines in SkipListener like this:
class SkipListener {
public static final Logger logger = LoggerFactory.getLogger(SkipListener.class);
#OnSkipInWrite
public void onSkipInWrite(Object item, Throwable t) {
onSkip(item);
}
#OnSkipInRead
public void onSkipInRead(Throwable t) {
if (t instanceof FlatFileParseException) {
FlatFileParseException ffpe = (FlatFileParseException) t;
onSkip(ffpe.getInput());
}
}
#OnSkipInProcess
public void onSkipInProcess(Object item, Throwable t) {
onSkip(item);
}
public void onSkip(Object item) {
logger.info(item);
}
}

How to create a variable that can be set only once but isn't final in Java

I want a class that I can create instances of with one variable unset (the id), then initialise this variable later, and have it immutable after initialisation. Effectively, I'd like a final variable that I can initialise outside of the constructor.
Currently, I'm improvising this with a setter that throws an Exception as follows:
public class Example {
private long id = 0;
// Constructors and other variables and methods deleted for clarity
public long getId() {
return id;
}
public void setId(long id) throws Exception {
if ( this.id == 0 ) {
this.id = id;
} else {
throw new Exception("Can't change id once set");
}
}
}
Is this a good way of going about what I'm trying to do? I feel like I should be able to set something as immutable after it's initialised, or that there is a pattern I can use to make this more elegant.
Let me suggest you a little bit more elegant decision.
First variant (without throwing an exception):
public class Example {
private Long id;
// Constructors and other variables and methods deleted for clarity
public long getId() {
return id;
}
public void setId(long id) {
this.id = this.id == null ? id : this.id;
}
}
Second variant (with throwing an exception):
public void setId(long id) {
this.id = this.id == null ? id : throw_();
}
public int throw_() {
throw new RuntimeException("id is already set");
}
The "set only once" requirement feels a bit arbitrary. I'm fairly certain what you're looking for is a class that transitions permanently from uninitialized to initialized state. After all, it may be convenient to set an object's id more than once (via code reuse or whatever), as long as the id is not allowed to change after the object is "built".
One fairly reasonable pattern is to keep track of this "built" state in a separate field:
public final class Example {
private long id;
private boolean isBuilt;
public long getId() {
return id;
}
public void setId(long id) {
if (isBuilt) throw new IllegalArgumentException("already built");
this.id = id;
}
public void build() {
isBuilt = true;
}
}
Usage:
Example e = new Example();
// do lots of stuff
e.setId(12345L);
e.build();
// at this point, e is immutable
With this pattern, you construct the object, set its values (as many times as is convenient), and then call build() to "immutify" it.
There are several advantages to this pattern over your initial approach:
There are no magic values used to represent uninitialized fields. For example, 0 is just as valid an id as any other long value.
Setters have a consistent behavior. Before build() is called, they work. After build() is called, they throw, regardless of what values you pass. (Note the use of unchecked exceptions for convenience).
The class is marked final, otherwise a developer could extend your class and override the setters.
But this approach has a fairly big drawback: developers using this class can't know, at compile time, if a particular object has been initialized or not. Sure, you could add an isBuilt() method so developers can check, at runtime, if the object is initialized, but it would be so much more convenient to know this information at compile time. For that, you could use the builder pattern:
public final class Example {
private final long id;
public Example(long id) {
this.id = id;
}
public long getId() {
return id;
}
public static class Builder {
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Example build() {
return new Example(id);
}
}
}
Usage:
Example.Builder builder = new Example.Builder();
builder.setId(12345L);
Example e = builder.build();
This is much better for several reasons:
We're using final fields, so both the compiler and developers know these values cannot be changed.
The distinction between initialized and uninitialized forms of the object is described via Java's type system. There is simply no setter to call on the object once it has been built.
Instances of the built class are guaranteed thread safe.
Yes, it's a bit more complicated to maintain, but IMHO the benefits outweigh the cost.
I recently had this problem when writing some code to construct an immutable cyclic graph where edges reference their nodes. I also noticed that none of the existing answers to this question are thread-safe (which actually allows the field to be set more than once), so I thought that I would contribute my answer. Basically, I just created a wrapper class called FinalReference which wraps an AtomicReference and leverages AtomicReference's compareAndSet() method. By calling compareAndSet(null, newValue), you can ensure that a new value is set at most once by multiple concurrently modifying threads. The call is atomic and will only succeed if the existing value is null. See the example source below for FinalReference and the Github link for sample test code to demonstrate correctness.
public final class FinalReference<T> {
private final AtomicReference<T> reference = new AtomicReference<T>();
public FinalReference() {
}
public void set(T value) {
this.reference.compareAndSet(null, value);
}
public T get() {
return this.reference.get();
}
}
Google's Guava library (which I recommend very highly) comes with a class that solves this problem very well: SettableFuture. This provides the set-once semantics that you ask about, but also a lot more:
The ability to communicate an exception instead (the setException method);
The ability to cancel the event explicitly;
The ability to register listeners that will be notified when the value is set, an exception is notified or the future is canceled (the ListenableFuture interface).
The Future family of types in general used for synchronization between threads in multithreaded programs, so SettableFuture plays very nicely with these.
Java 8 also has its own version of this: CompletableFuture.
You can simply add a boolean flag, and in your setId(), set/check the boolean. If I understood the question right, we don't need any complex structure/pattern here. How about this:
public class Example {
private long id = 0;
private boolean touched = false;
// Constructors and other variables and methods deleted for clarity
public long getId() {
return id;
}
public void setId(long id) throws Exception {
if ( !touchted ) {
this.id = id;
touched = true;
} else {
throw new Exception("Can't change id once set");
}
}
}
in this way, if you setId(0l); it thinks that the ID is set too. You can change if it is not right for your business logic requirement.
not edited it in an IDE, sorry for the typo/format problem, if there was...
Here's the solution I came up with based on mixing some of the answers and comments above, particularly one from #KatjaChristiansen on using assert.
public class Example {
private long id = 0L;
private boolean idSet = false;
public long getId() {
return id;
}
public void setId(long id) {
// setId should not be changed after being set for the first time.
assert ( !idSet ) : "Can't change id from " + this.id + " to " + id;
this.id = id;
idSet = true;
}
public boolean isIdSet() {
return idSet;
}
}
At the end of the day, I suspect that my need for this is an indication of poor design decisions elsewhere, and I should rather find a way of creating the object only when I know the Id, and setting the id to final. This way, more errors can be detected at compile time.
I have this class, similar to JDK's AtomicReference, and I use it mostly for legacy code:
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;
#NotThreadSafe
public class PermanentReference<T> {
private T reference;
public PermanentReference() {
}
public void set(final #Nonnull T reference) {
checkState(this.reference == null,
"reference cannot be set more than once");
this.reference = checkNotNull(reference);
}
public #Nonnull T get() {
checkState(reference != null, "reference must be set before get");
return reference;
}
}
I has single responsibilty and check both get and set calls, so it fails early when client code misuse it.
Here are two ways; the first is basically the same as some others mentioned in other answers, but it is here to constrast with the seconds. So the first way, Once is to have a value that can be set only once by enforcing that in the setter. My implementation requires non-null values, but if you want to be able to set to null, then you would need to implement an 'isSet' boolean flag as suggested in other answers.
The second way, Lazy, is to provide a function that lazily supplies the value once the first time the getter is called.
import javax.annotation.Nonnull;
public final class Once<T>
{
private T value;
public set(final #Nonnull T value)
{
if(null != this.value) throw new IllegalStateException("Illegal attempt to set a Once value after it's value has already been set.");
if(null == value) throw new IllegalArgumentException("Illegal attempt to pass null value to Once setter.");
this.value = value;
}
public #Nonnull T get()
{
if(null == this.value) throw new IllegalStateException("Illegal attempt to access unitialized Once value.");
return this.value;
}
}
public final class Lazy<T>
{
private Supplier<T> supplier;
private T value;
/**
* Construct a value that will be lazily intialized the
* first time the getter is called.
*
* #param the function that supplies the value or null if the value
* will always be null. If it is not null, it will be called
* at most one time.
*/
public Lazy(final Supplier<T> supplier)
{
this.supplier = supplier;
}
/**
* Get the value. The first time this is called, if the
* supplier is not null, it will be called to supply the
* value.
*
* #returns the value (which may be null)
*/
public T get()
{
if(null != this.supplier)
{
this.value = this.supplier.get();
this.supplier = null; // clear the supplier so it is not called again
// and can be garbage collected.
}
return this.value;
}
}
So you might use these as follows;
//
// using Java 8 syntax, but this is not a hard requirement
//
final Once<Integer> i = Once<>();
i.set(100);
i.get(); // returns 100
// i.set(200) would throw an IllegalStateException
final Lazy<Integer> j = Lazy<>(() -> i);
j.get(); // returns 100
try have an int checker like
private long id = 0;
static int checker = 0;
public void methodThatWillSetValueOfId(stuff){
checker = checker + 1
if (checker==1){
id = 123456;
}
}
//u can try this:
class Star
{
private int i;
private int j;
static boolean a=true;
Star(){i=0;j=0;}
public void setI(int i,int j) {
this.i =i;
this.j =j;
something();
a=false;
}
public void printVal()
{
System.out.println(i+" "+j);
}
public static void something(){
if(!a)throw new ArithmeticException("can't assign value");
}
}
public class aClass
{
public static void main(String[] args) {
System.out.println("");
Star ob = new Star();
ob.setI(5,6);
ob.printVal();
ob.setI(6,7);
ob.printVal();
}
}
Marking a field private and not exposing a setter should be sufficient:
public class Example{
private long id=0;
public Example(long id)
{
this.id=id;
}
public long getId()
{
return this.id;
}
if this is insufficient and you want someone to be able to modify it X times you can do this:
public class Example
{
...
private final int MAX_CHANGES = 1;
private int changes = 0;
public void setId(long id) throws Exception {
validateExample();
changes++;
if ( this.id == 0 ) {
this.id = id;
} else {
throw new Exception("Can't change id once set");
}
}
private validateExample
{
if(MAX_CHANGES==change)
{
throw new IllegalStateException("Can no longer update this id");
}
}
}
This approach is akin to design by contract, wherein you validate the state of the object after a mutator (something that changes the state of the object) is invoked.
I think the singleton pattern might be something you should look into. Google around a bit to check if this pattern meets your design goals.
Below is some sudo code on how to make a singleton in Java using enum. I think this is based off Joshua Bloch's design outlined in Effective Java, either way it's a book worth picking up if you don't have it yet.
public enum JavaObject {
INSTANCE;
public void doSomething(){
System.out.println("Hello World!");
}
}
Usage:
JavaObject.INSTANCE.doSomething();

How to get a Text field from a appengine datastore element from the client side

I have a class to be saved into appengine datastore, which among others contains, a Text field (String-like appengine datatype, but not limited to 500 chars). Also a twin class which is basically the same, but is used on the client side (ie without any com.google.appengine.api.datastore.* import).
Is there any datatype, which would let me save the Text server-side field into client-Side?
A possible option would be split the Text into some Strings, but that sounds pretty ugly...
Any suggestions?
You can call getValue() to make it a String.
You can use Text for your persistable field. You just need to have a RPC serializer to be able to use it on the client (in GWT).
Take a look at http://blog.js-development.com/2010/02/gwt-app-engine-and-app-engine-data.html, it explains how to do it.
some additions to custom serializable libraries posted before
( http://juristr.com/blog/2010/02/gwt-app-engine-and-app-engine-data/
http://www.resmarksystems.com/code/
- get com.google.appengine.api.datastore.Text and other datastore types transferred to client)
need also to update com.google.appengine.eclipse.core.prefs to include library:
filesCopiedToWebInfLib=...|appengine-utils-client-1.1.jar
another workaround is making string serializable blob to overcome 1500 bytes limit (it will lost sort and filter ability fir this field):
#Persistent(serialized = "true")
public String content;
it is possible to have less overhead on client with converting from com.google.appengine.api.datastore.Text to String with lifecycle listeners (not instance listeners, they will got send to client and make it fail). use it together with custom serialization which allows client support for com.google.appengine.api.datastore.Text with no additional transport class is required.
com.google.appengine.api.datastore.Text may be cleared before sending to client to avoid sending overhead (simplest way is to mark it transient).
on server side we have to avoid setting String property directly, because jdo will not catch it change (will catch only for new records or when some persistent field is modified after). this is very little overhead.
detaching of records should be performed via pm.makeTransient. when using pm.detachCopy it is required to mark entity as detachable = "true" (DetachLifecycleListener to be called) and implement DetachLifecycleListener.postDetach similar way as StoreLifecycleListener.preStore. othwerwise non-persistent fields will not be copied (by pm.detachCopy) and will be empty on client.
it is possible to handle several classes similar way
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.listener.DetachLifecycleListener;
import javax.jdo.listener.InstanceLifecycleEvent;
import javax.jdo.listener.LoadLifecycleListener;
import javax.jdo.listener.StoreLifecycleListener;
import com.google.appengine.api.datastore.Text;
import com.mycompany.mywebapp.shared.Entity;
import com.mycompany.mywebapp.shared.Message;
#SuppressWarnings("rawtypes")
public class PersistenceManagerStuff
{
public static final PersistenceManagerFactory PMF = JDOHelper.getPersistenceManagerFactory("transactions-optional");
public static EntityLifecycleListener entityLifecycleListener = new EntityLifecycleListener();
public static Class[] entityClassList = new Class[] { Entity.class };
public static MessageLifecycleListener messageLifecycleListener = new MessageLifecycleListener();
public static Class[] messageClassList = new Class[] { Message.class };
public static PersistenceManager getPersistenceManager()
{
PersistenceManager pm = PMF.getPersistenceManager();
pm.addInstanceLifecycleListener(entityLifecycleListener, entityClassList);
pm.addInstanceLifecycleListener(messageLifecycleListener, messageClassList);
return pm;
}
// [start] lifecycle listeners
public static class EntityLifecycleListener implements LoadLifecycleListener, StoreLifecycleListener//, DetachLifecycleListener
{
public void postLoad(InstanceLifecycleEvent event)
{
Entity entity = ((Entity) event.getSource());
if (entity.content_long != null)
entity.content = entity.content_long.getValue();
else
entity.content = null;
}
public void preStore(InstanceLifecycleEvent event)
{
Entity entity = ((Entity) event.getSource());
entity.setContent(entity.content);
/*
need mark class #PersistenceAware to use code below, otherwise use setter
if (entity.content != null)
entity.content_long = new Text(entity.content);
else
entity.content_long = null;
*/
}
public void postStore(InstanceLifecycleEvent event)
{
}
/*public void postDetach(InstanceLifecycleEvent event)
{
}
public void preDetach(InstanceLifecycleEvent event)
{
}*/
}
public static class MessageLifecycleListener implements LoadLifecycleListener, StoreLifecycleListener
{
public void postLoad(InstanceLifecycleEvent event)
{
Message message = ((Message) event.getSource());
if (message.content_long != null)
message.content = message.content_long.getValue();
else
message.content = null;
}
public void preStore(InstanceLifecycleEvent event)
{
Message message = ((Message) event.getSource());
message.setContent(message.content);
}
public void postStore(InstanceLifecycleEvent event)
{
}
}
// [end] lifecycle listeners
}
#SuppressWarnings("serial")
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "false")
public class Entity implements Serializable
{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
public Long id;
#NotPersistent
public String content;
#Persistent(column = "content")
public transient com.google.appengine.api.datastore.Text content_long;
public void setContent(String content)
{
this.content = content;
if (content != null)
content_long = new Text(content);
else
content_long = null;
}
public Entity() {}
}
#PersistenceAware
public class DataServiceImpl extends RemoteServiceServlet implements DataService
{
public Entity renameEntity(long id, String newContent) throws NotLoggedInException
{
PersistenceManager pm = PersistenceManagerStuff.getPersistenceManager();
Entity result = null;
try
{
Entity entity = (Entity) pm.getObjectById(Entity.class, id);
if (entity.longUserId != getLongUserId(pm))
throw new NotLoggedInException(String.format("wrong entity %d ownership", entity.id));
entity.modificationDate = java.lang.System.currentTimeMillis(); // will call lifecycle handlers for entity.content, but is still old value
//entity.content = newContent; // will not work, even owner class is #PersistenceAware
entity.setContent(newContent); // correct way to set long value
pm.makeTransient(result = entity);
}
catch (Exception e)
{
LOG.log(Level.WARNING, e.getMessage());
throw e;
}
finally
{
pm.close();
}
return result;
}
}
also in lifecycle handlers it is possible to mix old (short) and new (long) values into single entity if you have both (with different field names) and do not want to convert old to new. but is seems com.google.appengine.api.datastore.Text supports loading from old String values.
some low-level code to batch convert old values into new (using low level com.google.appengine.api.datastore api):
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Query q = new Query("Entity");
PreparedQuery pq = datastore.prepare(q);
for (com.google.appengine.api.datastore.Entity result : pq.asIterable())
{
String content = (String) result.getProperty("content");
if (content != null)
{
result.setProperty("content", new com.google.appengine.api.datastore.Text(content));
datastore.put(result);
}
}

Categories