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