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}