五:ORM框架Morphia的学习-Update

时间:2021-02-22 08:44:36

介绍


有两种方法更新啦。第一种: insert/save 。第二种: update operation。

下面开始讨论。.

Updating (on the server)

当你调用update方法时,你其实就是发生一个修改命令给数据库。作用?当然是修改已存在的数据啦。


MongoDB Docs on Updating

interface Datastore {
...

       
/** updates all entities found with the operations*/
       
<T> UpdateResults<T> update(Query<T> query, UpdateOperations<T> ops);
       
/** updates all entities found with the operations; if nothing is found insert the update as an entity if "createIfMissing" is true*/
       
<T> UpdateResults<T> update(Query<T> query, UpdateOperations<T> ops, boolean createIfMissing);
       
/** updates the first entity found with the operations*/
       
<T> UpdateResults<T> updateFirst(Query<T> query, UpdateOperations<T> ops);
       
/** updates the first entity found with the operations; if nothing is found insert the update as an entity if "createIfMissing" is true*/
       
<T> UpdateResults<T> updateFirst(Query<T> query, UpdateOperations<T> ops, boolean createIfMissing);
       
/** updates the first entity found with the operations; if nothing is found insert the update as an entity if "createIfMissing" is true*/
       
<T> UpdateResults<T> updateFirst(Query<T> query, T entity, boolean createIfMissing);
}
public interface UpdateOperations<T> {
       
/** sets the field value */
       
UpdateOperations<T> set(String fieldExpr, Object value);
       
/** removes the field */
       
UpdateOperations<T> unset(String fieldExpr);

       
/** adds the value to an array field*/
       
UpdateOperations<T> add(String fieldExpr, Object value);
       
UpdateOperations<T> add(String fieldExpr, Object value, boolean addDups);
       
/** adds the values to an array field*/
       
UpdateOperations<T> addAll(String fieldExpr, List<?> values, boolean addDups);
       
       
/** removes the first value from the array*/
       
UpdateOperations<T> removeFirst(String fieldExpr);
       
/** removes the last value from the array*/
       
UpdateOperations<T> removeLast(String fieldExpr);
       
/** removes the value from the array field*/
       
UpdateOperations<T> removeAll(String fieldExpr, Object value);
       
/** removes the values from the array field*/
       
UpdateOperations<T> removeAll(String fieldExpr, List<?> values);

       
/** decrements the numeric field by 1*/
       
UpdateOperations<T> dec(String fieldExpr);
       
/** increments the numeric field by 1*/
       
UpdateOperations<T> inc(String fieldExpr);
       
/** increments the numeric field by value (negatives are allowed)*/
       
UpdateOperations<T> inc(String fieldExpr, Number value);
}


The Field Expression

属性表达式可以作用于所有的操作。可以是一个的属性,也可以是点嵌套的属性。你也可以使用 ($)在属性表达式中。

Samples initialization

Morphia morphia = new Morphia();
morphia
.map(Hotel.class).map(Address.class);
Datastore datastore = morphia.createDatastore("MorphiaSampleDb");
Hotel hotel = new Hotel("Fairmont", 3, new Address("1 Rideau Street", "Ottawa", "K1N8S7", "Canada"));
datastore
.save(hotel);
UpdateOperations<Hotel> ops;

// This query will be used in the samples to restrict the update operations to only the hotel we just created.
// If this was not supplied, by default the update() operates on all documents in the collection.
// We could use any field here but _id will be unique and mongodb by default puts an index on the _id field so this should be fast!
Query<Hotel> updateQuery = datastore.createQuery(Hotel.class).field("_id").equal(hotel.getId());

// The Mapper class also provides a public static of the default _id field name for us...
Query<Hotel> updateQuery = datastore.createQuery(Hotel.class).field(Mapper.ID_KEY).equal(hotel.getId());


注意:使用的是 equal(),而不是 equals()

@Entity("hotels")
public class Hotel
{
   
@Id
   
private ObjectId id;

   
private String name;
   
private int stars;

   
@Embedded
   
private Address address;

   
@Embedded
   
List<Integer> roomNumbers = new ArrayList<Integer>();

   
// ... getters and setters
}

@Embedded
public class Address
{
   
private String street;
   
private String city;
   
private String postalCode;
   
private String country;

   
// ... getters and setters
}

set/unset

// change the name of the hotel
ops
= datastore.createUpdateOperations(Hotel.class).set("name", "Fairmont Chateau Laurier");
datastore
.update(updateQuery, ops);

// also works for embedded documents, change the name of the city in the address
ops
= datastore.createUpdateOperations(Hotel.class).set("address.city", "Ottawa");
datastore
.update(updateQuery, ops);

// remove the name property from the document
// causes the next load of the Hotel to have name = null
ops
= datastore.createUpdateOperations(Hotel.class).unset("name");
datastore
.update(updateQuery, ops);

inc/dec

// increment 'stars' by 1
ops
= datastore.createUpdateOperations(Hotel.class).inc("stars");
datastore
.update(updateQuery, ops);

// increment 'stars' by 4
ops
= datastore.createUpdateOperations(Hotel.class).inc("stars", 4);
datastore
.update(updateQuery, ops);

// decrement 'stars' by 1
ops
= datastore.createUpdateOperations(Hotel.class).dec("stars");  // same as .inc("stars", -1)
datastore
.update(updateQuery, ops);

// decrement 'stars' by 4
ops
= datastore.createUpdateOperations(Hotel.class).inc("stars", -4);
datastore
.update(updateQuery, ops);

add/All

// push a value onto an array() (+v 0.95) 
// same as .add("roomNumbers", 11, false)
ops
= datastore.createUpdateOperations(Hotel.class).add("roomNumbers", 11);
datastore
.update(updateQuery, ops); // [ 11 ]


当你向一个不是数组的属性,进行数组的操作。会报错的。

ops = datastore.createUpdateOperations(Hotel.class).set("roomNumbers", 11);
datastore
.update(updateQuery, ops);

// causes error since 'roomNumbers' is not an array at this point
ops
= datastore.createUpdateOperations(Hotel.class).add("roomNumbers", 11, false);
datastore
.update(updateQuery, ops);  // causes error

// delete the property
ops
= datastore.createUpdateOperations(Hotel.class).unset("roomNumbers");
datastore
.update(updateQuery, ops);

// use the 3rd parameter to add duplicates

// add to end of array, same as add()
ops
= datastore.createUpdateOperations(Hotel.class).add("roomNumbers", 11, false);
datastore
.update(updateQuery, ops);  // [ 11 ]

// no change since its a duplicate... doesn't cause error
ops
= datastore.createUpdateOperations(Hotel.class).add("roomNumbers", 11, false);
datastore
.update(updateQuery, ops);  // [ 11 ]

// push onto the end of the array
ops
= datastore.createUpdateOperations(Hotel.class).add("roomNumbers", 12, false);
datastore
.update(updateQuery, ops); // [ 11, 12 ]

// add even if its a duplicate
ops
= datastore.createUpdateOperations(Hotel.class).add("roomNumbers", 11, true);
datastore
.update(updateQuery, ops); // [ 11, 12, 11 ]

removeFirst/Last/All

//given roomNumbers = [ 1, 2, 3 ]
ops
= datastore.createUpdateOperations(Hotel.class).removeFirst("roomNumbers");
datastore
.update(updateQuery, ops);  // [ 2, 3 ]


//given roomNumbers = [ 1, 2, 3 ]
ops
= datastore.createUpdateOperations(Hotel.class).removeLast("roomNumbers");
datastore
.update(updateQuery, ops);  // [ 1, 2 ]
ops
= datastore.createUpdateOperations(Hotel.class).removeLast("roomNumbers");
datastore
.update(updateQuery, ops);  // [ 1 ]
ops
= datastore.createUpdateOperations(Hotel.class).removeLast("roomNumbers");
datastore
.update(updateQuery, ops);  // []   empty array


//given roomNumbers = [ 1, 2, 3, 3 ]
ops
= datastore.createUpdateOperations(Hotel.class).removeAll("roomNumbers", 3);
datastore
.update(updateQuery, ops);  // [ 1, 2 ]

//given roomNumbers = [ 1, 2, 3, 3 ]
ops
= datastore.createUpdateOperations(Hotel.class).removeAll("roomNumbers", Arrays.asList(2, 3));
datastore
.update(updateQuery, ops);  // [ 1 ]

Multiple Operations

你也可以在一个operation里面做多个操作。

//set city to Ottawa and increment stars by 1
ops
= datastore.createUpdateOperations(Hotel.class).set("city", "Ottawa").inc("stars");
datastore
.update(updateQuery, ops);

//if you perform multiple operations in one command on the same property, results will vary
ops
= datastore.createUpdateOperations(Hotel.class).inc("stars", 50).inc("stars");  //increments by 1
ops
= datastore.createUpdateOperations(Hotel.class).inc("stars").inc("stars", 50);  //increments by 50

//you can't apply conflicting operations to the same property
ops
= datastore.createUpdateOperations(Hotel.class).set("stars", 1).inc("stars", 50); //causes error

updateFirst method

In the default driver and shell this is the default behavior. In Morphia we feel like updating all the results of the query is a better default (see below).

{ name: "Fairmont", stars: 5}, { name: "Last Chance", stars: 3 }

ops = datastore.createUpdateOperations(Hotel.class).inc("stars", 50);

// (+v 0.95 now takes into account the order())
// morphia exposes a specific updateFirst to update only the first hotel matching the query
datastore
.updateFirst(datastore.find(Hotel.class).order("stars"), ops);  // update only Last Chance
datastore
.updateFirst(datastore.find(Hotel.class).order("-stars"), ops); // update only Fairmont
//default shell version is to match first
//shell version has a multi to indicate to update all matches, not just first
//to mimic morphia operation, set multi = false
db
.collection.update( criteria, objNew, upsert, multi );

update method

ops = datastore.createUpdateOperations(Hotel.class).inc("stars", 50);

// morphia default update is to update all the hotels
datastore
.update(datastore.createQuery(Hotel.class), ops);  //increments all hotels
//equivalent morphia shell version is... upsert = false, multi = true
db
.collection.update( criteria, objNew, false, true );

createIfMissing (overload parameter)

all of the update methods are overloaded and accept a "createIfMissing" parameter

ops = datastore.createUpdateOperations(Hotel.class).inc("stars", 50);

//update, if not found create it
datastore
.updateFirst(datastore.createQuery(Hotel.class).field("stars").greaterThan(100), ops, true);  

// creates { "_id" : ObjectId("4c60629d2f1200000000161d"), "stars" : 50 }
//equivalent morphia shell version is... upsert = true
db
.collection.update( criteria, objNew, true, multi );