简体   繁体   中英

Strange thing in Play 1.2.x when working with database

I found strange behaviour in my Play 1.2.x application

For example we has following code:

app/models/Account.java:

package models;

import javax.persistence.Entity;

import play.db.jpa.Model;

@Entity
public class Account extends Model {

    public String username;
}

app/coutrollers/Application.java:

package controllers;

import play.mvc.Controller;

import java.util.List;

import models.Account;

public class Application extends Controller {

    public static void index() {
        Account account = Account.find("username LIKE ?", "username1").first();
        account.username = "username3";
        List<Account> accounts = Account.all().fetch();
        render(account, accounts);
    }
}

app/views/Application/index.html:

#{extends 'main.html' /}
#{set title:'Home' /}

<h2>Working!</h2>

${account.username}

<ul>
  #{list items:accounts, as:'acc'}
    <li>${acc.username}</li>
  #{/list}
</ul>

With following accounts in database:

  • username1
  • username2

Output will be following:

Working!

username3

  • username3
  • username2

But must be as:

Working!

username3

  • username1
  • username2

What is this???

  • Play bug?
  • Java static context feature?
  • JPA feature?
  • ...?

RESOLVED

Thanks for @millimoose. All that needs is a detach() :

package controllers;

import play.mvc.Controller;

import java.util.List;

import models.Account;

import play.db.jpa.JPA;

public class Application extends Controller {

    public static void index() {
        Account account = Account.find("username LIKE ?", "username1").first();
        account.username = "username3";
        JPA.em().detach(account);
        List<Account> accounts = Account.all().fetch();
        render(account, accounts);
    }
}

JPA works just like every other ORM on earth, in that when you look up the same database record twice, you will get the same object. The .first() query caches the Account internally (to track changes done to it done within a unit of work), and the .all().fetch() call just gives you that cached object again.

I'm not familiar with the Play! ORM stuff, but "raw" JPA has EntityManager.detach() to make it stop tracking a given entity instance. (And thus give you a new copy whenever the corresponding DB record is retrieved again.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM