簡體   English   中英

Spring JPA-更新多個字段的最佳方法

[英]Spring JPA - Best way to update multiple fields

我是使用JPA的新手,並嘗試將我的代碼從JdbcTemplate過渡到JPA。 最初,我通過獲取列及其值的映射來更新列的子集,並親自創建SQL Update字符串並使用DAO執行它。 我想知道使用JPA做類似事情的最佳方法是什么?

編輯:
如何將這段代碼從DAO轉換為JPA中的等效代碼?

public void updateFields(String userId, Map<String, String> fields) {
    StringBuilder sb = new StringBuilder();
    for (Entry<String, String> entry : fields.entrySet()) {
        sb.append(entry.getKey());
        sb.append("='");
        sb.append(StringEscapeUtils.escapeEcmaScript(entry.getValue()));
        sb.append("', ");
    }

    String str = sb.toString();
    if (str.length() > 2) {
        str = str.substring(0, str.length() - 2); // remove ", "
        String sql = "UPDATE users_table SET " + str + " WHERE user_id=?";
        jdbcTemplate.update(sql, new Object[] { userId },
                new int[] { Types.VARCHAR });
    }
}

您必須確定要閱讀有關JPA更多信息:)

實體進入Persistence Context ,JPA提供程序將對其進行跟蹤,直到持久性上下文生存期結束或直到調用EntityManager#detach()方法為止。 當事務完成(提交)時,持久性上下文中的受管實體的狀態將與數據庫同步,並進行所有更改。

如果您的實體是新實體,則可以通過調用EntityManager#persist()方法將其置於持久性上下文中。

對於您的情況(現有實體的更新),您必須從數據庫中獲取一行並將其更改為實體。 它可以通過多種方式完成,但最簡單的方法是調用EntityManager#find()方法,該方法將返回托管實體。 返回的對象也將置於當前的持久性上下文中,因此,如果有活動的事務,則可以更改所需的任何屬性(而不是主鍵),並通過調用commit來完成事務(或者如果這是容器管理的事務,則為finish方法) )。

更新

在您發表評論后,我可以看到您的觀點。 我認為您應該重新設計應用程序以適合JPA標准和功能。 無論如何-如果您已經有一對<Attribute_name, Attrbute_value>對的映射<Attribute_name, Attrbute_value>可以使用一個稱為Metamodel的東西。 簡單用法如下所示。 這是幼稚的實現,僅適用於基本屬性,您應該注意關系等。(可以通過attr.getJavaType()attr.getPersistentAttributeType()方法來獲取有關屬性的更多信息)

Metamodel meta = entityManager.getMetamodel();
EntityType<User> user_ = meta.entity(User.class);

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaUpdate<User> update = cb.createCriteriaUpdate(User.class);

Root e = update.from(User.class);

for( Attribute<? super User, ?> attr : user_.getAttributes() ) {
      if (map.containsKey(attr.getName())) {
          update.set(attr, map.get(attr));
      }
}

update.where(cb.equal(e.get("id"), idOfUser));
entityManager.createQuery(update).executeUpdate();

請注意,自2.1版本開始,JPA中提供了更新條件查詢。

在這里,您可以找到有關元模型生成的更多信息。

除了元模型,您還可以使用Java反射機制。

JPA處理更新。 使用entitymanager將數據集作為實體檢索,更改值並調用持久化。 這會將更改的數據存儲在您的數據庫中。

如果您使用的是Hibernate(作為JPA提供程序),這是一個示例

實體

@Entity
@Table(name="PERSON")
public class Person {

    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

    @Column(name="NAME", nullable=false)
    private String name;

    other fields....
}

public interface PersonDao  {
    Person findById(int id);    
    void persist(Person person);

    ...
}

道普

@Repository("personDao")
public class PersonDaoImpl extends AnAbstractClassWithSessionFactory implements PersonDao {

    public Person findById(int id) {
        return (Person) getSession().get(Person.class, id);
    }

    public void persist(Person person){
       getSession().persist(person);
    }
}

服務

@Service("personService")
@Transactional
public class PersonServiceImpl implements PersonService {

    @Autowired
    PersonDao personDao;

    @Override
    public void createAndPersist(SomeSourceObject object) {
      //create Person object and populates with the source object
      Person person = new Person();     
      person.name = object.name;
      ...
      personDao.persist(person);
    }

    @Override
    public Person findById(int id) {
        return personDao.findById(id);
    }

    public void doSomethingWithPerson(Person person) {
         person.setName(person.getName()+" HELLO "); 
    //here since we are in transaction, no need to explicitly call update/merge
    //it will be updated in db as soon as the methods completed successfully
    //OR
    //changes will be undone if transaction failed/rolledback
   }
}

對於詳細信息,JPA文檔確實是很好的資源。

從設計的角度來看,如果您具有Web接口,我傾向於說再包括一個服務委托層(例如,PersonDelegateService),它將從UI接收的實際數據映射到人實體(反之亦然,以進行顯示)以填充視圖對象。人員實體)並委托服務進行實際人員實體處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM