001package io.ebean;
002
003import io.ebean.bean.EntityBean;
004
005import java.util.Collection;
006
007/**
008 * Provides finder functionality for use with "Dependency Injection style" use of Ebean.
009 * <p>
010 * <pre>{@code
011 *
012 * @Repository
013 * public class CustomerRepository extends BeanRepository<Long,Customer> {
014 *
015 *   @Inject
016 *   public CustomerRepository(EbeanServer server) {
017 *     super(Customer.class, server);
018 *   }
019 *
020 *   // ... add customer specific finders and persist logic
021 *
022 *   public List<Customer> findByName(String nameStart) {
023 *     return query().where()
024 *             .istartsWith("name", nameStart)
025 *             .findList();
026 *   }
027 *
028 * }
029 * }</pre>
030 *
031 * @param <I> The ID type
032 * @param <T> The Bean type
033 */
034public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
035
036  /**
037   * Create with the given bean type and EbeanServer instance.
038   * <p>
039   * Typically users would extend BeanRepository rather than BeanFinder.
040   * </p>
041   * <pre>{@code
042   *
043   *   @Inject
044   *   public CustomerRepository(EbeanServer server) {
045   *     super(Customer.class, server);
046   *   }
047   *
048   * }</pre>
049   *
050   * @param type   The bean type
051   * @param server The EbeanServer instance typically created via Spring factory or equivalent
052   */
053  protected BeanRepository(Class<T> type, EbeanServer server) {
054    super(type, server);
055  }
056
057  /**
058   * Marks the entity bean as dirty.
059   * <p>
060   * This is used so that when a bean that is otherwise unmodified is updated the version
061   * property is updated.
062   * <p>
063   * An unmodified bean that is saved or updated is normally skipped and this marks the bean as
064   * dirty so that it is not skipped.
065   * <p>
066   * <pre>{@code
067   *
068   * Customer customer = customerRepository.byId(id);
069   *
070   * // mark the bean as dirty so that a save() or update() will
071   * // increment the version property
072   *
073   * customerRepository.markAsDirty(customer);
074   * customerRepository.save(customer);
075   *
076   * }</pre>
077   *
078   * @see EbeanServer#markAsDirty(Object)
079   */
080  public void markAsDirty(T bean) {
081    db().markAsDirty(bean);
082  }
083
084  /**
085   * Mark the property as unset or 'not loaded'.
086   * <p>
087   * This would be used to specify a property that we did not wish to include in a stateless update.
088   * </p>
089   * <pre>{@code
090   *
091   *   // populate an entity bean from JSON or whatever
092   *   Customer customer = ...;
093   *
094   *   // mark the email property as 'unset' so that it is not
095   *   // included in a 'stateless update'
096   *   customerRepository.markPropertyUnset(customer, "email");
097   *
098   *   customerRepository.update(customer);
099   *
100   * }</pre>
101   *
102   * @param propertyName the name of the property on the bean to be marked as 'unset'
103   */
104  public void markPropertyUnset(T bean, String propertyName) {
105    ((EntityBean) bean)._ebean_getIntercept().setPropertyLoaded(propertyName, false);
106  }
107
108  /**
109   * Insert or update this entity depending on its state.
110   * <p>
111   * Ebean will detect if this is a new bean or a previously fetched bean and perform either an
112   * insert or an update based on that.
113   *
114   * @see EbeanServer#save(Object)
115   */
116  public void save(T bean) {
117    db().save(bean);
118  }
119
120  /**
121   * Save all the beans in the collection.
122   */
123  public int saveAll(Collection<T> bean) {
124    return db().saveAll(bean);
125  }
126
127  /**
128   * Update this entity.
129   *
130   * @see EbeanServer#update(Object)
131   */
132  public void update(T bean) {
133    db().update(bean);
134  }
135
136  /**
137   * Insert this entity.
138   *
139   * @see EbeanServer#insert(Object)
140   */
141  public void insert(T bean) {
142    db().insert(bean);
143  }
144
145  /**
146   * Delete this bean.
147   * <p>
148   * This will return true if the bean was deleted successfully or JDBC batch is being used.
149   * </p>
150   * <p>
151   * If there is no current transaction one will be created and committed for
152   * you automatically.
153   * </p>
154   * <p>
155   * If the Bean does not have a version property (or loaded version property) and
156   * the bean does not exist then this returns false indicating that nothing was
157   * deleted. Note that, if JDBC batch mode is used then this always returns true.
158   * </p>
159   *
160   * @see EbeanServer#delete(Object)
161   */
162  public boolean delete(T bean) {
163    return db().delete(bean);
164  }
165
166  /**
167   * Delete all the beans in the collection.
168   */
169  public int deleteAll(Collection<T> beans) {
170    return db().deleteAll(beans);
171  }
172
173  /**
174   * Delete a bean permanently without soft delete.
175   * <p>
176   * This is used when the bean contains a <code>@SoftDelete</code> property and we
177   * want to perform a hard/permanent delete.
178   * </p>
179   *
180   * @see EbeanServer#deletePermanent(Object)
181   */
182  public boolean deletePermanent(T bean) {
183    return db().deletePermanent(bean);
184  }
185
186  /**
187   * Merge this entity using the default merge options.
188   * <p>
189   * Ebean will detect if this is a new bean or a previously fetched bean and perform either an
190   * insert or an update based on that.
191   *
192   * @see EbeanServer#merge(Object)
193   */
194  public void merge(T bean) {
195    db().merge(bean);
196  }
197
198  /**
199   * Merge this entity using the specified merge options.
200   * <p>
201   * Ebean will detect if this is a new bean or a previously fetched bean and perform either an
202   * insert or an update based on that.
203   *
204   * @see EbeanServer#merge(Object, MergeOptions)
205   */
206  public void merge(T bean, MergeOptions options) {
207    db().merge(bean, options);
208  }
209
210  /**
211   * Refreshes this entity from the database.
212   *
213   * @see EbeanServer#refresh(Object)
214   */
215  public void refresh(T bean) {
216    db().refresh(bean);
217  }
218}