list2 = DB.findNative(Contact.class, "select * from contract where firstName like :name")
34 | .setParameter("name", "f%")
35 | .findList();
36 |
37 | System.out.println("list2 " + list2);
38 |
39 | System.out.println("done");
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/MyAddress.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | import jakarta.persistence.Entity;
4 | import jakarta.persistence.Id;
5 |
6 | @Entity
7 | public class MyAddress {
8 |
9 | @Id
10 | public long id;
11 | public String line1;
12 | public String city;
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/MyPerson.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | import io.ebean.Model;
4 | import io.ebean.annotation.WhenCreated;
5 | import io.ebean.annotation.WhenModified;
6 |
7 | import jakarta.persistence.Entity;
8 | import jakarta.persistence.Id;
9 | import jakarta.persistence.ManyToOne;
10 | import jakarta.persistence.Version;
11 |
12 | import java.time.Instant;
13 |
14 | import static jakarta.persistence.CascadeType.PERSIST;
15 |
16 | @Entity
17 | public class MyPerson extends Model {
18 |
19 | @Id
20 | public long id;
21 | public String name;
22 | public String notes;
23 | public String foo;
24 |
25 | @ManyToOne(cascade = PERSIST)
26 | public MyAddress address;
27 |
28 | @WhenCreated
29 | public Instant whenCreated;
30 | @WhenModified
31 | public Instant whenModified;
32 | @Version
33 | public long version;
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/Address.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.annotation.StorageEngine;
4 | import org.example.domain.finder.AddressFinder;
5 | import jakarta.persistence.Entity;
6 | import jakarta.persistence.ManyToOne;
7 | import jakarta.persistence.Table;
8 | import jakarta.validation.constraints.Size;
9 |
10 | /**
11 | * Address entity bean.
12 | */
13 | @StorageEngine("ENGINE = Log()")
14 | @Entity
15 | @Table(name = "address")
16 | public class Address extends BaseModel {
17 |
18 | public static final AddressFinder find = new AddressFinder();
19 |
20 | @Size(max = 100)
21 | String line1;
22 |
23 | @Size(max = 100)
24 | String line2;
25 |
26 | @Size(max = 100)
27 | String city;
28 |
29 | @ManyToOne
30 | Country country;
31 |
32 | /**
33 | * Create a copy of the address. Used to provide a 'snapshot' of
34 | * the shippingAddress for a give order.
35 | */
36 | public Address createCopy() {
37 | Address copy = new Address();
38 | copy.setLine1(line1);
39 | copy.setLine2(line2);
40 | copy.setCity(city);
41 | copy.setCountry(country);
42 | return copy;
43 | }
44 |
45 | public String toString() {
46 | return id + " " + line1 + " " + line2 + " " + city + " " + country;
47 | }
48 |
49 | /**
50 | * Return line 1.
51 | */
52 | public String getLine1() {
53 | return line1;
54 | }
55 |
56 | /**
57 | * Set line 1.
58 | */
59 | public void setLine1(String line1) {
60 | this.line1 = line1;
61 | }
62 |
63 | /**
64 | * Return line 2.
65 | */
66 | public String getLine2() {
67 | return line2;
68 | }
69 |
70 | /**
71 | * Set line 2.
72 | */
73 | public void setLine2(String line2) {
74 | this.line2 = line2;
75 | }
76 |
77 | /**
78 | * Return city.
79 | */
80 | public String getCity() {
81 | return city;
82 | }
83 |
84 | /**
85 | * Set city.
86 | */
87 | public void setCity(String city) {
88 | this.city = city;
89 | }
90 |
91 | /**
92 | * Return country.
93 | */
94 | public Country getCountry() {
95 | return country;
96 | }
97 |
98 | /**
99 | * Set country.
100 | */
101 | public void setCountry(Country country) {
102 | this.country = country;
103 | }
104 |
105 | }
106 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/BaseModel.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.Model;
4 | import io.ebean.annotation.WhenCreated;
5 | import io.ebean.annotation.WhenModified;
6 |
7 | import jakarta.persistence.Id;
8 | import jakarta.persistence.MappedSuperclass;
9 | import jakarta.persistence.Version;
10 | import java.time.Instant;
11 |
12 | /**
13 | * Base domain object with id, version, whenCreated and whenModified.
14 | *
15 | *
16 | * Extending Model to enable the 'active record' style.
17 | *
18 | *
19 | * whenCreated and whenModified are generally useful for maintaining external search services (like
20 | * elasticsearch) and audit.
21 | */
22 | @MappedSuperclass
23 | public abstract class BaseModel extends Model {
24 |
25 | @Id
26 | long id;
27 |
28 | @Version
29 | Long version;
30 |
31 | @WhenCreated
32 | Instant whenCreated;
33 |
34 | @WhenModified
35 | Instant whenModified;
36 |
37 | public long getId() {
38 | return id;
39 | }
40 |
41 | public void setId(long id) {
42 | this.id = id;
43 | }
44 |
45 | public Long getVersion() {
46 | return version;
47 | }
48 |
49 | public void setVersion(Long version) {
50 | this.version = version;
51 | }
52 |
53 | public Instant getWhenCreated() {
54 | return whenCreated;
55 | }
56 |
57 | public void setWhenCreated(Instant whenCreated) {
58 | this.whenCreated = whenCreated;
59 | }
60 |
61 | public Instant getWhenModified() {
62 | return whenModified;
63 | }
64 |
65 | public void setWhenModified(Instant whenModified) {
66 | this.whenModified = whenModified;
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/Contact.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import org.example.domain.finder.ContactFinder;
4 |
5 | import jakarta.persistence.Column;
6 | import jakarta.persistence.Entity;
7 | import jakarta.persistence.Lob;
8 | import jakarta.persistence.ManyToOne;
9 | import jakarta.persistence.Table;
10 |
11 | /**
12 | * Contact entity bean.
13 | */
14 | @Entity
15 | @Table(name="contact")
16 | public class Contact extends BaseModel {
17 |
18 | public static final ContactFinder find = new ContactFinder();
19 |
20 | @Column(length=50, nullable = false)
21 | String firstName;
22 |
23 | @Column(length=50)
24 | String lastName;
25 |
26 | @Column(length=200)
27 | String email;
28 |
29 | @Column(length=20)
30 | String phone;
31 |
32 | @ManyToOne(optional=false)
33 | Customer customer;
34 |
35 | @Lob
36 | String comments;
37 |
38 | // @OneToMany(mappedBy = "contact")
39 | // List notes;
40 |
41 | /**
42 | * Default constructor.
43 | */
44 | public Contact() {
45 | }
46 |
47 | /**
48 | * Construct with a firstName and lastName.
49 | */
50 | public Contact(String firstName, String lastName) {
51 | this.firstName = firstName;
52 | this.lastName = lastName;
53 | }
54 |
55 | public Contact(Customer customer, String firstName, String lastName) {
56 | this(firstName, lastName);
57 | this.customer = customer;
58 | }
59 |
60 | public String getFirstName() {
61 | return firstName;
62 | }
63 |
64 | public void setFirstName(String firstName) {
65 | this.firstName = firstName;
66 | }
67 |
68 | public String getLastName() {
69 | return lastName;
70 | }
71 |
72 | public void setLastName(String lastName) {
73 | this.lastName = lastName;
74 | }
75 |
76 | public String getEmail() {
77 | return email;
78 | }
79 |
80 | public void setEmail(String email) {
81 | this.email = email;
82 | }
83 |
84 | public String getPhone() {
85 | return phone;
86 | }
87 |
88 | public void setPhone(String phone) {
89 | this.phone = phone;
90 | }
91 |
92 | public Customer getCustomer() {
93 | return customer;
94 | }
95 |
96 | public void setCustomer(Customer customer) {
97 | this.customer = customer;
98 | }
99 |
100 | public String getComments() {
101 | return comments;
102 | }
103 |
104 | public void setComments(String comments) {
105 | this.comments = comments;
106 | }
107 |
108 | // public List getNotes() {
109 | // return notes;
110 | // }
111 | //
112 | // public void setNotes(List notes) {
113 | // this.notes = notes;
114 | // }
115 | }
116 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/Content.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.Model;
4 |
5 | import jakarta.persistence.Entity;
6 | import jakarta.persistence.Id;
7 | import java.util.UUID;
8 |
9 | @Entity
10 | public class Content extends Model {
11 |
12 | @Id
13 | UUID id;
14 |
15 | String name;
16 |
17 | public Content(String name) {
18 | this.name = name;
19 | }
20 |
21 | public UUID getId() {
22 | return id;
23 | }
24 |
25 | public void setId(UUID id) {
26 | this.id = id;
27 | }
28 |
29 | public String getName() {
30 | return name;
31 | }
32 |
33 | public void setName(String name) {
34 | this.name = name;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/Country.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.Model;
4 | import io.ebean.annotation.Cache;
5 | import org.example.domain.finder.CountryFinder;
6 |
7 | import jakarta.persistence.Entity;
8 | import jakarta.persistence.Id;
9 | import jakarta.persistence.Table;
10 | import jakarta.validation.constraints.Size;
11 |
12 | /**
13 | * Country entity bean.
14 | */
15 | @Cache
16 | @Entity
17 | @Table(name = "country")
18 | public class Country extends Model {
19 |
20 | public static final CountryFinder find = new CountryFinder();
21 |
22 | @Id
23 | @Size(max = 2)
24 | final String code;
25 |
26 | @Size(max = 60)
27 | final String name;
28 |
29 | public Country(String code, String name) {
30 | this.code = code;
31 | this.name = name;
32 | }
33 |
34 |
35 | public String toString() {
36 | return code;
37 | }
38 |
39 | /**
40 | * Return code.
41 | */
42 | public String getCode() {
43 | return code;
44 | }
45 |
46 | /**
47 | * Return name.
48 | */
49 | public String getName() {
50 | return name;
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/Customer.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.annotation.DbArray;
4 | import io.ebean.annotation.DbComment;
5 | import org.example.domain.finder.CustomerFinder;
6 |
7 | import jakarta.persistence.Column;
8 | import jakarta.persistence.Embedded;
9 | import jakarta.persistence.Entity;
10 | import jakarta.persistence.Lob;
11 | import jakarta.persistence.ManyToOne;
12 | import jakarta.persistence.OneToMany;
13 | import jakarta.persistence.Table;
14 | import jakarta.validation.constraints.NotNull;
15 | import jakarta.validation.constraints.Size;
16 | import java.net.InetAddress;
17 | import java.time.LocalDate;
18 | import java.util.ArrayList;
19 | import java.util.List;
20 | import java.util.UUID;
21 |
22 | import static jakarta.persistence.CascadeType.PERSIST;
23 |
24 | /**
25 | * Customer entity bean.
26 | *
27 | * This example shows an entity bean without a default constructor. The name property is
28 | * expected to be final and non-null. Note the InsertCustomerTest.testRef() test showing
29 | * loading the partially loaded bean.
30 | */
31 | @DbComment("Customer table general comment")
32 | @Entity
33 | @Table(name = "customer")
34 | public class Customer extends BaseModel {
35 |
36 | public static final CustomerFinder find = new CustomerFinder();
37 |
38 | boolean inactive;
39 |
40 | @NotNull
41 | @Column(unique = true)
42 | @Size(min = 1, max = 100)
43 | String name;
44 |
45 | @DbComment("The date the customer first registered")
46 | LocalDate registered;
47 |
48 | @DbArray
49 | List uids = new ArrayList<>();
50 |
51 | @Embedded
52 | SomeEmbedd some;
53 |
54 | PhoneNumber phoneNumber;
55 |
56 | @Lob
57 | String comments;
58 |
59 | @ManyToOne(cascade = PERSIST)
60 | Address billingAddress;
61 |
62 | @ManyToOne(cascade = PERSIST)
63 | Address shippingAddress;
64 |
65 | @OneToMany(mappedBy = "customer", cascade = PERSIST)
66 | List contacts;
67 |
68 | @OneToMany(mappedBy = "customer")
69 | List orders;
70 |
71 | InetAddress lastAddr;
72 |
73 | public Customer(String name) {
74 | this.name = name;
75 | }
76 |
77 | public String toString() {
78 | return "id:" + id + " name:" + name;
79 | }
80 |
81 | /**
82 | * Helper method to add a contact to the customer.
83 | */
84 | public void addContact(Contact contact) {
85 | contacts.add(contact);
86 | }
87 |
88 | // AUTOGENERATED START
89 | public List getUids() {
90 | return uids;
91 | }
92 |
93 | public void setUids(List uids) {
94 | this.uids = uids;
95 | }
96 |
97 | public boolean isInactive() {
98 | return inactive;
99 | }
100 |
101 | public void setInactive(boolean inactive) {
102 | this.inactive = inactive;
103 | }
104 |
105 | public String getName() {
106 | return name;
107 | }
108 |
109 | public void setName(String name) {
110 | this.name = name;
111 | }
112 |
113 | public PhoneNumber getPhoneNumber() {
114 | return phoneNumber;
115 | }
116 |
117 | public void setPhoneNumber(PhoneNumber phoneNumber) {
118 | this.phoneNumber = phoneNumber;
119 | }
120 |
121 | public LocalDate getRegistered() {
122 | return registered;
123 | }
124 |
125 | public void setRegistered(LocalDate registered) {
126 | this.registered = registered;
127 | }
128 |
129 | public String getComments() {
130 | return comments;
131 | }
132 |
133 | public Customer comments(String comments) {
134 | this.comments = comments;
135 | return this;
136 | }
137 |
138 | public Address getBillingAddress() {
139 | return billingAddress;
140 | }
141 |
142 | public void setBillingAddress(Address billingAddress) {
143 | this.billingAddress = billingAddress;
144 | }
145 |
146 | public Address getShippingAddress() {
147 | return shippingAddress;
148 | }
149 |
150 | public void setShippingAddress(Address shippingAddress) {
151 | this.shippingAddress = shippingAddress;
152 | }
153 |
154 | public List getContacts() {
155 | return contacts;
156 | }
157 |
158 | public void setContacts(List contacts) {
159 | this.contacts = contacts;
160 | }
161 |
162 | public List getOrders() {
163 | return orders;
164 | }
165 |
166 | public void setOrders(List orders) {
167 | this.orders = orders;
168 | }
169 | // AUTOGENERATED END
170 | }
171 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/CustomerPersistAdapter.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.annotation.EbeanComponent;
4 | import io.ebean.event.BeanPersistAdapter;
5 | import io.ebean.event.BeanPersistRequest;
6 |
7 | @EbeanComponent
8 | public class CustomerPersistAdapter extends BeanPersistAdapter {
9 |
10 | @Override
11 | public boolean isRegisterFor(Class> cls) {
12 | return Customer.class.equals(cls);
13 | }
14 |
15 | @Override
16 | public void postInsert(BeanPersistRequest> request) {
17 | final Object bean = request.bean();
18 | System.out.println("postInsert " + bean);
19 | }
20 |
21 | @Override
22 | public void postUpdate(BeanPersistRequest> request) {
23 | final Object bean = request.bean();
24 | System.out.println("postUpdate " + bean + " updated:" + request.updatedProperties() + " dirty:" + request.updatedValues());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/DMachine.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.Model;
4 |
5 | import jakarta.persistence.Entity;
6 | import jakarta.persistence.Id;
7 | import jakarta.persistence.Version;
8 |
9 | @Entity
10 | public class DMachine extends Model {
11 |
12 | @Id
13 | long id;
14 |
15 | String name;
16 |
17 | @Version
18 | long version;
19 |
20 | public DMachine(String name) {
21 | this.name = name;
22 | }
23 |
24 | public long getId() {
25 | return id;
26 | }
27 |
28 | public void setId(long id) {
29 | this.id = id;
30 | }
31 |
32 | public String getName() {
33 | return name;
34 | }
35 |
36 | public void setName(String name) {
37 | this.name = name;
38 | }
39 |
40 | public long getVersion() {
41 | return version;
42 | }
43 |
44 | public void setVersion(long version) {
45 | this.version = version;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/DMachineStats.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import jakarta.persistence.Entity;
4 | import jakarta.persistence.Id;
5 | import jakarta.persistence.ManyToOne;
6 | import jakarta.persistence.Table;
7 | import jakarta.persistence.Version;
8 | import java.math.BigDecimal;
9 | import java.time.LocalDate;
10 |
11 | @Entity
12 | @Table(name = "d_machine_stats")
13 | public class DMachineStats {
14 |
15 | @Id
16 | long id;
17 |
18 | @ManyToOne
19 | DMachine machine;
20 |
21 | LocalDate date;
22 |
23 | long totalKms;
24 |
25 | long hours;
26 |
27 | BigDecimal rate;
28 |
29 | BigDecimal cost;
30 |
31 | @Version
32 | long version;
33 |
34 | public DMachineStats(DMachine machine, LocalDate date) {
35 | this.machine = machine;
36 | this.date = date;
37 | }
38 |
39 | public long getId() {
40 | return id;
41 | }
42 |
43 | public void setId(long id) {
44 | this.id = id;
45 | }
46 |
47 | public DMachine getMachine() {
48 | return machine;
49 | }
50 |
51 | public void setMachine(DMachine machine) {
52 | this.machine = machine;
53 | }
54 |
55 | public LocalDate getDate() {
56 | return date;
57 | }
58 |
59 | public void setDate(LocalDate date) {
60 | this.date = date;
61 | }
62 |
63 | public long getTotalKms() {
64 | return totalKms;
65 | }
66 |
67 | public void setTotalKms(long totalKms) {
68 | this.totalKms = totalKms;
69 | }
70 |
71 | public long getHours() {
72 | return hours;
73 | }
74 |
75 | public void setHours(long hours) {
76 | this.hours = hours;
77 | }
78 |
79 | public BigDecimal getRate() {
80 | return rate;
81 | }
82 |
83 | public void setRate(BigDecimal rate) {
84 | this.rate = rate;
85 | }
86 |
87 | public BigDecimal getCost() {
88 | return cost;
89 | }
90 |
91 | public void setCost(BigDecimal cost) {
92 | this.cost = cost;
93 | }
94 |
95 | public long getVersion() {
96 | return version;
97 | }
98 |
99 | public void setVersion(long version) {
100 | this.version = version;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/DMachineStatsAgg.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.annotation.Aggregation;
4 | import io.ebean.annotation.View;
5 |
6 | import jakarta.persistence.Entity;
7 | import jakarta.persistence.ManyToOne;
8 | import java.math.BigDecimal;
9 | import java.time.LocalDate;
10 |
11 | @Entity
12 | @View(name = "d_machine_stats", dependentTables = "d_machine_stats")
13 | public class DMachineStatsAgg {
14 |
15 | @ManyToOne
16 | DMachine machine;
17 |
18 | LocalDate date;
19 |
20 | /**
21 | * Matching with column underscore.
22 | */
23 | @Aggregation("sum(totalKms)")
24 | long totalKms;
25 |
26 | /**
27 | * Matching with no underscore.
28 | */
29 | @Aggregation("sum(hours)")
30 | long hours;
31 |
32 | @Aggregation("max(rate)")
33 | BigDecimal rate;
34 |
35 | /**
36 | * Not matching.
37 | */
38 | @Aggregation("sum(cost)")
39 | BigDecimal totalCost;
40 |
41 | /**
42 | * Not matching.
43 | */
44 | @Aggregation("max(totalKms)")
45 | BigDecimal maxKms;
46 |
47 | public DMachine getMachine() {
48 | return machine;
49 | }
50 |
51 | public void setMachine(DMachine machine) {
52 | this.machine = machine;
53 | }
54 |
55 | public LocalDate getDate() {
56 | return date;
57 | }
58 |
59 | public void setDate(LocalDate date) {
60 | this.date = date;
61 | }
62 |
63 | public long getTotalKms() {
64 | return totalKms;
65 | }
66 |
67 | public void setTotalKms(long totalKms) {
68 | this.totalKms = totalKms;
69 | }
70 |
71 | public long getHours() {
72 | return hours;
73 | }
74 |
75 | public void setHours(long hours) {
76 | this.hours = hours;
77 | }
78 |
79 | public BigDecimal getRate() {
80 | return rate;
81 | }
82 |
83 | public void setRate(BigDecimal rate) {
84 | this.rate = rate;
85 | }
86 |
87 | public BigDecimal getTotalCost() {
88 | return totalCost;
89 | }
90 |
91 | public void setTotalCost(BigDecimal totalCost) {
92 | this.totalCost = totalCost;
93 | }
94 |
95 | public BigDecimal getMaxKms() {
96 | return maxKms;
97 | }
98 |
99 | public void setMaxKms(BigDecimal maxKms) {
100 | this.maxKms = maxKms;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/Order.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.annotation.Aggregation;
4 | import io.ebean.annotation.EnumValue;
5 | import org.example.domain.finder.OrderFinder;
6 |
7 | import jakarta.persistence.CascadeType;
8 | import jakarta.persistence.Entity;
9 | import jakarta.persistence.ManyToOne;
10 | import jakarta.persistence.OneToMany;
11 | import jakarta.persistence.OrderBy;
12 | import jakarta.persistence.Table;
13 | import jakarta.validation.constraints.NotNull;
14 | import java.time.LocalDate;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | /**
19 | * Order entity bean.
20 | */
21 | @Entity
22 | @Table(name = "orders")
23 | public class Order extends BaseModel {
24 |
25 | public static final OrderFinder find = new OrderFinder();
26 |
27 | public enum Status {
28 | @EnumValue("N")
29 | NEW,
30 | @EnumValue("A")
31 | APPROVED,
32 | @EnumValue("S")
33 | SHIPPED,
34 | @EnumValue("C")
35 | COMPLETE,
36 | @EnumValue("F")
37 | FOO
38 | }
39 |
40 | @NotNull
41 | Status status;
42 |
43 | LocalDate orderDate;
44 |
45 | @Aggregation("max(orderDate)")
46 | LocalDate maxOrderDate;
47 |
48 | @Aggregation("count(*)")
49 | Long totalCount;
50 |
51 | LocalDate shipDate;
52 |
53 | @ManyToOne(optional = false)
54 | Customer customer;
55 |
56 | @ManyToOne
57 | Address shippingAddress;
58 |
59 | @OrderBy("id asc")
60 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "order")
61 | List details = new ArrayList<>();
62 |
63 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "order")
64 | List shipments = new ArrayList<>();
65 |
66 | public Order(Customer customer) {
67 | this.status = Status.NEW;
68 | this.customer = customer;
69 | this.orderDate = LocalDate.now();
70 | }
71 |
72 | public String toString() {
73 | return id + " status:" + status + " customer:" + customer;
74 | }
75 |
76 | /**
77 | * Return order date.
78 | */
79 | public LocalDate getOrderDate() {
80 | return orderDate;
81 | }
82 |
83 | /**
84 | * Set order date.
85 | */
86 | public void setOrderDate(LocalDate orderDate) {
87 | this.orderDate = orderDate;
88 | }
89 |
90 | /**
91 | * Return ship date.
92 | */
93 | public LocalDate getShipDate() {
94 | return shipDate;
95 | }
96 |
97 | /**
98 | * Set ship date.
99 | */
100 | public void setShipDate(LocalDate shipDate) {
101 | this.shipDate = shipDate;
102 | }
103 |
104 | /**
105 | * Return status.
106 | */
107 | public Status getStatus() {
108 | return status;
109 | }
110 |
111 | /**
112 | * Set status.
113 | */
114 | public void setStatus(Status status) {
115 | this.status = status;
116 | }
117 |
118 | /**
119 | * Return customer.
120 | */
121 | public Customer getCustomer() {
122 | return customer;
123 | }
124 |
125 | /**
126 | * Set customer.
127 | */
128 | public void setCustomer(Customer customer) {
129 | this.customer = customer;
130 | }
131 |
132 | /**
133 | * Set the customer with their current shipping address.
134 | */
135 | public void setCustomerWithShipping(Customer customer) {
136 | this.customer = customer;
137 | this.shippingAddress = customer.getShippingAddress();
138 | }
139 |
140 | public List getShipments() {
141 | return shipments;
142 | }
143 |
144 | public void setShipments(List shipments) {
145 | this.shipments = shipments;
146 | }
147 |
148 | /**
149 | * Return details.
150 | */
151 | public List getDetails() {
152 | return details;
153 | }
154 |
155 | /**
156 | * Set details.
157 | */
158 | public void setDetails(List details) {
159 | this.details = details;
160 | }
161 |
162 | public void addDetail(OrderDetail detail) {
163 |
164 | if (details == null) {
165 | details = new ArrayList();
166 | }
167 | details.add(detail);
168 | }
169 |
170 | public LocalDate getMaxOrderDate() {
171 | return maxOrderDate;
172 | }
173 |
174 | public void setMaxOrderDate(LocalDate maxOrderDate) {
175 | this.maxOrderDate = maxOrderDate;
176 | }
177 |
178 | public Long getTotalCount() {
179 | return totalCount;
180 | }
181 |
182 | public void setTotalCount(Long totalCount) {
183 | this.totalCount = totalCount;
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/OrderDetail.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import org.example.domain.finder.OrderDetailFinder;
4 | import jakarta.persistence.Entity;
5 | import jakarta.persistence.ManyToOne;
6 | import jakarta.persistence.Table;
7 |
8 | /**
9 | * Order Detail entity bean.
10 | */
11 | @Entity
12 | @Table(name = "order_detail")
13 | public class OrderDetail extends BaseModel {
14 |
15 | public static final OrderDetailFinder find = new OrderDetailFinder();
16 |
17 | @ManyToOne
18 | Order order;
19 |
20 | Integer orderQty;
21 |
22 | Integer shipQty;
23 |
24 | Double unitPrice;
25 |
26 | @ManyToOne
27 | Product product;
28 |
29 | public OrderDetail() {
30 | }
31 |
32 | public OrderDetail(Product product, Integer orderQty, Double unitPrice) {
33 | this.product = product;
34 | this.orderQty = orderQty;
35 | this.unitPrice = unitPrice;
36 | }
37 |
38 | /**
39 | * Return order qty.
40 | */
41 | public Integer getOrderQty() {
42 | return orderQty;
43 | }
44 |
45 | /**
46 | * Set order qty.
47 | */
48 | public void setOrderQty(Integer orderQty) {
49 | this.orderQty = orderQty;
50 | }
51 |
52 | /**
53 | * Return ship qty.
54 | */
55 | public Integer getShipQty() {
56 | return shipQty;
57 | }
58 |
59 | /**
60 | * Set ship qty.
61 | */
62 | public void setShipQty(Integer shipQty) {
63 | this.shipQty = shipQty;
64 | }
65 |
66 | public Double getUnitPrice() {
67 | return unitPrice;
68 | }
69 |
70 | public void setUnitPrice(Double unitPrice) {
71 | this.unitPrice = unitPrice;
72 | }
73 |
74 | /**
75 | * Return order.
76 | */
77 | public Order getOrder() {
78 | return order;
79 | }
80 |
81 | /**
82 | * Set order.
83 | */
84 | public void setOrder(Order order) {
85 | this.order = order;
86 | }
87 |
88 | /**
89 | * Return product.
90 | */
91 | public Product getProduct() {
92 | return product;
93 | }
94 |
95 | /**
96 | * Set product.
97 | */
98 | public void setProduct(Product product) {
99 | this.product = product;
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/OrderShipment.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import org.example.domain.finder.OrderShipmentFinder;
4 | import jakarta.persistence.Entity;
5 | import jakarta.persistence.ManyToOne;
6 | import jakarta.persistence.Table;
7 | import java.time.LocalDate;
8 |
9 | @Entity
10 | @Table(name="order_shipment")
11 | public class OrderShipment extends BaseModel {
12 |
13 | public static final OrderShipmentFinder find = new OrderShipmentFinder();
14 |
15 | @ManyToOne(optional = false)
16 | Order order;
17 |
18 | LocalDate shippedOn;
19 |
20 | String notes;
21 |
22 | public OrderShipment(String notes) {
23 | this.notes = notes;
24 | this.shippedOn = LocalDate.now();
25 | }
26 |
27 | public LocalDate getShippedOn() {
28 | return shippedOn;
29 | }
30 |
31 | public void setShippedOn(LocalDate shippedOn) {
32 | this.shippedOn = shippedOn;
33 | }
34 |
35 | public String getNotes() {
36 | return notes;
37 | }
38 |
39 | public void setNotes(String notes) {
40 | this.notes = notes;
41 | }
42 |
43 | public Order getOrder() {
44 | return order;
45 | }
46 |
47 | public void setOrder(Order order) {
48 | this.order = order;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/OrderTotals.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.annotation.Cache;
4 | import io.ebean.annotation.View;
5 | import org.example.domain.finder.OrderTotalsFinder;
6 |
7 | import jakarta.persistence.Entity;
8 | import jakarta.persistence.Id;
9 | import jakarta.persistence.OneToOne;
10 |
11 | @Cache(enableQueryCache = true)
12 | @Entity
13 | @View(name = "order_agg_vw", dependentTables="order")
14 | public class OrderTotals {
15 |
16 | public static final OrderTotalsFinder find = new OrderTotalsFinder();
17 |
18 | @Id
19 | Long id;
20 |
21 | @OneToOne
22 | Order order;
23 |
24 | Double orderTotal;
25 |
26 | Double shipTotal;
27 |
28 | public Long getId() {
29 | return id;
30 | }
31 |
32 | public void setId(Long id) {
33 | this.id = id;
34 | }
35 |
36 | public Double getOrderTotal() {
37 | return orderTotal;
38 | }
39 |
40 | public void setOrderTotal(Double orderTotal) {
41 | this.orderTotal = orderTotal;
42 | }
43 |
44 | public Double getShipTotal() {
45 | return shipTotal;
46 | }
47 |
48 | public void setShipTotal(Double shipTotal) {
49 | this.shipTotal = shipTotal;
50 | }
51 |
52 | public Order getOrder() {
53 | return order;
54 | }
55 |
56 | public void setOrder(Order order) {
57 | this.order = order;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/PhoneNumber.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | public record PhoneNumber(String value) {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/PhoneNumberConverter.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import jakarta.persistence.AttributeConverter;
4 | import jakarta.persistence.Converter;
5 |
6 | @Converter
7 | public class PhoneNumberConverter implements AttributeConverter {
8 |
9 | @Override
10 | public String convertToDatabaseColumn(PhoneNumber attribute) {
11 | return attribute.value();
12 | }
13 |
14 | @Override
15 | public PhoneNumber convertToEntityAttribute(String dbData) {
16 | return new PhoneNumber(dbData);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/Product.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import org.example.domain.finder.ProductFinder;
4 | import org.example.domain.query.QProduct;
5 |
6 | import jakarta.persistence.Entity;
7 | import jakarta.persistence.Id;
8 | import jakarta.persistence.Table;
9 | import jakarta.validation.constraints.Size;
10 |
11 | /**
12 | * Product entity bean.
13 | */
14 | @Entity
15 | @Table(name = "product")
16 | public class Product {
17 |
18 | public static final ProductFinder find = new ProductFinder();
19 |
20 | @Id
21 | Long id;
22 |
23 | @Size(max = 20)
24 | String sku;
25 |
26 | @Size(max = 50)
27 | String name;
28 |
29 | public Product(String sku, String name) {
30 | this.sku = sku;
31 | this.name = name;
32 | }
33 |
34 | public Long getId() {
35 | return id;
36 | }
37 |
38 | public void setId(Long id) {
39 | this.id = id;
40 | }
41 |
42 | /**
43 | * Return sku.
44 | */
45 | public String getSku() {
46 | return sku;
47 | }
48 |
49 | /**
50 | * Set sku.
51 | */
52 | public void setSku(String sku) {
53 | this.sku = sku;
54 | }
55 |
56 | /**
57 | * Return name.
58 | */
59 | public String getName() {
60 | return name;
61 | }
62 |
63 | /**
64 | * Set name.
65 | */
66 | public void setName(String name) {
67 | this.name = name;
68 | }
69 |
70 | public static Product byName(String name) {
71 | return new QProduct()
72 | .name.equalTo(name)
73 | .findOne();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/SomeEmbedd.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import jakarta.persistence.Embeddable;
4 |
5 | @Embeddable
6 | public class SomeEmbedd {
7 |
8 | String one;
9 | String two;
10 | String three;
11 |
12 | public String getOne() {
13 | return one;
14 | }
15 |
16 | public void setOne(String one) {
17 | this.one = one;
18 | }
19 |
20 | public String getTwo() {
21 | return two;
22 | }
23 |
24 | public void setTwo(String two) {
25 | this.two = two;
26 | }
27 |
28 | public String getThree() {
29 | return three;
30 | }
31 |
32 | public void setThree(String three) {
33 | this.three = three;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/finder/AddressFinder.java:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder;
2 |
3 | import io.ebean.Finder;
4 | import org.example.domain.Address;
5 |
6 | public class AddressFinder extends Finder {
7 |
8 | /**
9 | * Construct using the default EbeanServer.
10 | */
11 | public AddressFinder() {
12 | super(Address.class);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/finder/ContactFinder.java:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder;
2 |
3 | import io.ebean.Finder;
4 | import org.example.domain.Contact;
5 |
6 | public class ContactFinder extends Finder {
7 |
8 | /**
9 | * Construct using the default EbeanServer.
10 | */
11 | public ContactFinder() {
12 | super(Contact.class);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/finder/CountryFinder.java:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder;
2 |
3 | import io.ebean.Finder;
4 | import org.example.domain.Country;
5 |
6 | public class CountryFinder extends Finder {
7 |
8 | /**
9 | * Construct using the default EbeanServer.
10 | */
11 | public CountryFinder() {
12 | super(Country.class);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/finder/CustomerFinder.java:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder;
2 |
3 | import io.ebean.Finder;
4 | import org.example.domain.Customer;
5 |
6 | public class CustomerFinder extends Finder {
7 |
8 | /**
9 | * Construct using the default EbeanServer.
10 | */
11 | public CustomerFinder() {
12 | super(Customer.class);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/finder/OrderDetailFinder.java:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder;
2 |
3 | import io.ebean.Finder;
4 | import org.example.domain.OrderDetail;
5 |
6 | public class OrderDetailFinder extends Finder {
7 |
8 | /**
9 | * Construct using the default EbeanServer.
10 | */
11 | public OrderDetailFinder() {
12 | super(OrderDetail.class);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/finder/OrderFinder.java:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder;
2 |
3 | import io.ebean.Finder;
4 | import org.example.domain.Order;
5 |
6 | public class OrderFinder extends Finder {
7 |
8 | /**
9 | * Construct using the default EbeanServer.
10 | */
11 | public OrderFinder() {
12 | super(Order.class);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/finder/OrderShipmentFinder.java:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder;
2 |
3 | import io.ebean.Finder;
4 | import org.example.domain.OrderShipment;
5 |
6 | public class OrderShipmentFinder extends Finder {
7 |
8 | /**
9 | * Construct using the default EbeanServer.
10 | */
11 | public OrderShipmentFinder() {
12 | super(OrderShipment.class);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/finder/OrderTotalsFinder.java:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder;
2 |
3 | import io.ebean.Finder;
4 | import org.example.domain.OrderTotals;
5 |
6 | public class OrderTotalsFinder extends Finder {
7 |
8 | /**
9 | * Construct using the default EbeanServer.
10 | */
11 | public OrderTotalsFinder() {
12 | super(OrderTotals.class);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/domain/finder/ProductFinder.java:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder;
2 |
3 | import io.ebean.Finder;
4 | import org.example.domain.Product;
5 |
6 | public class ProductFinder extends Finder {
7 |
8 | /**
9 | * Construct using the default EbeanServer.
10 | */
11 | public ProductFinder() {
12 | super(Product.class);
13 | }
14 |
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/service/FooOne.java:
--------------------------------------------------------------------------------
1 | package org.example.service;
2 |
3 | import io.ebean.annotation.Transactional;
4 | import org.example.domain.Address;
5 | import org.example.domain.query.QAddress;
6 |
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | public class FooOne {
12 |
13 | public List findThemBe() {
14 | return new ArrayList<>();
15 | }
16 |
17 | public List findThem() {
18 | return new QAddress()
19 | .findList();
20 | }
21 |
22 | @Transactional
23 | public List findThemTxn() {
24 | return new QAddress()
25 | //.city.istartsWith("auck")
26 | .findList();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/base-example/src/main/java/org/example/service/LoadExampleData.java:
--------------------------------------------------------------------------------
1 | package org.example.service;
2 |
3 | import io.ebean.DB;
4 | import io.ebean.Transaction;
5 | import org.example.domain.Address;
6 | import org.example.domain.Contact;
7 | import org.example.domain.Country;
8 | import org.example.domain.Customer;
9 | import org.example.domain.Order;
10 | import org.example.domain.Order.Status;
11 | import org.example.domain.OrderDetail;
12 | import org.example.domain.Product;
13 | import org.slf4j.Logger;
14 | import org.slf4j.LoggerFactory;
15 |
16 | import java.time.LocalDate;
17 | import java.util.ArrayList;
18 | import java.util.List;
19 |
20 | public class LoadExampleData {
21 |
22 | private static final Logger log = LoggerFactory.getLogger(LoadExampleData.class);
23 |
24 | private static final LoadExampleData data = new LoadExampleData();
25 |
26 | private boolean runOnce;
27 |
28 | public static synchronized void load() {
29 |
30 | if (data.runOnce) {
31 | return;
32 | }
33 | data.loadAll();
34 | }
35 |
36 | private synchronized void loadAll() {
37 |
38 | log.info("loading test data ----------------------------------------------");
39 |
40 | runOnce = true;
41 | if (Country.find.query().findCount() > 0) {
42 | return;
43 | }
44 |
45 | try (Transaction transaction = DB.beginTransaction()) {
46 | try {
47 | deleteAll();
48 | insertReference();
49 | insertTestCustAndOrders();
50 | transaction.commit();
51 | } catch (Throwable e) {
52 | log.error("Error seeding", e);
53 | }
54 | }
55 | }
56 |
57 | private void insertReference() {
58 | insertCountries();
59 | insertProducts();
60 | }
61 |
62 |
63 | private void deleteAll() {
64 | DB.execute(() -> {
65 |
66 | // Ebean.currentTransaction().setBatchMode(false);
67 |
68 | // orm update use bean name and bean properties
69 | // server.createUpdate(OrderShipment.class, "delete from orderShipment").execute();
70 |
71 | DB.createUpdate(OrderDetail.class, "delete from orderDetail").execute();
72 | DB.createUpdate(Order.class, "delete from order").execute();
73 | DB.createUpdate(Contact.class, "delete from contact").execute();
74 | DB.createUpdate(Customer.class, "delete from Customer").execute();
75 | DB.createUpdate(Address.class, "delete from address").execute();
76 |
77 | // sql update uses table and column names
78 | DB.sqlUpdate("delete from country").execute();
79 | DB.sqlUpdate("delete from product").execute();
80 | });
81 | }
82 |
83 | private void insertCountries() {
84 |
85 | DB.execute(() -> {
86 | new Country("NZ", "New Zealand").save();
87 | new Country("AU", "Australia").save();
88 | });
89 | }
90 |
91 | private final List products = new ArrayList<>();
92 |
93 | private void insertProducts() {
94 |
95 | products.add(new Product("C001", "Chair"));
96 | products.add(new Product("DSK1", "Desk"));
97 | products.add(new Product("C002", "Computer"));
98 | products.add(new Product("C003", "Printer"));
99 |
100 | DB.saveAll(products);
101 | }
102 |
103 | private void insertTestCustAndOrders() {
104 |
105 | DB.execute(() -> {
106 | Customer cust1 = insertCustomer("Rob");
107 | Customer cust2 = insertCustomerNoAddress();
108 | insertCustomerFiona();
109 | insertCustomerNoContacts("NocCust");
110 |
111 | createOrder1(cust1);
112 | createOrder2(cust2);
113 | createOrder3(cust1);
114 | createOrder4(cust1);
115 | }
116 | );
117 | }
118 |
119 | private static int contactEmailNum = 1;
120 |
121 | private void insertCustomerFiona() {
122 |
123 | Customer c = createCustomer("Fiona", "12 Apple St", "West Coast Rd", 1);
124 |
125 | c.addContact(createContact("Fiona", "Black"));
126 | c.addContact(createContact("Tracy", "Red"));
127 |
128 | DB.save(c);
129 | }
130 |
131 | public static Contact createContact(String firstName, String lastName) {
132 | Contact contact = new Contact();
133 | contact.setFirstName(firstName);
134 | contact.setLastName(lastName);
135 | String email = contact.getLastName() + (contactEmailNum++) + "@test.com";
136 | contact.setEmail(email.toLowerCase());
137 | return contact;
138 | }
139 |
140 | private void insertCustomerNoContacts(String name) {
141 |
142 | Customer c = createCustomer(name, "15 Kumera Way", "Bos town", 1);
143 |
144 | DB.save(c);
145 | }
146 |
147 | private Customer insertCustomerNoAddress() {
148 |
149 | Customer c = new Customer("Jack Hill");
150 | c.addContact(createContact("Jack", "Black"));
151 | c.addContact(createContact("Jill", "Hill"));
152 | c.addContact(createContact("Mac", "Hill"));
153 |
154 | DB.save(c);
155 | return c;
156 | }
157 |
158 | private static Customer insertCustomer(String name) {
159 | Customer c = createCustomer(name, "1 Banana St", "P.O.Box 1234", 1);
160 | DB.save(c);
161 | return c;
162 | }
163 |
164 | private static Customer createCustomer(String name, String shippingStreet, String billingStreet, int contactSuffix) {
165 |
166 | Customer c = new Customer(name);
167 | if (contactSuffix > 0) {
168 | c.addContact(new Contact("Jim" + contactSuffix, "Cricket"));
169 | c.addContact(new Contact("Fred" + contactSuffix, "Blue"));
170 | c.addContact(new Contact("Bugs" + contactSuffix, "Bunny"));
171 | }
172 |
173 | if (shippingStreet != null) {
174 | Address shippingAddr = new Address();
175 | shippingAddr.setLine1(shippingStreet);
176 | shippingAddr.setLine2("Sandringham");
177 | shippingAddr.setCity("Auckland");
178 | shippingAddr.setCountry(Country.find.ref("NZ"));
179 |
180 | c.setShippingAddress(shippingAddr);
181 | }
182 |
183 | if (billingStreet != null) {
184 | Address billingAddr = new Address();
185 | billingAddr.setLine1(billingStreet);
186 | billingAddr.setLine2("St Lukes");
187 | billingAddr.setCity("Auckland");
188 | billingAddr.setCountry(DB.reference(Country.class, "NZ"));
189 |
190 | c.setBillingAddress(billingAddr);
191 | }
192 |
193 | return c;
194 | }
195 |
196 | private Order createOrder1(Customer customer) {
197 |
198 | // these id values are not predicable depending on DB Id type (Cockroach serial)
199 | Product product1 = Product.find.ref(products.get(0).getId());
200 | Product product2 = Product.find.ref(products.get(1).getId());
201 | Product product3 = Product.find.ref(products.get(2).getId());
202 |
203 | Order order = new Order(customer);
204 |
205 | List details = new ArrayList<>();
206 | details.add(new OrderDetail(product1, 5, 10.50));
207 | details.add(new OrderDetail(product2, 3, 1.10));
208 | details.add(new OrderDetail(product3, 1, 2.00));
209 | order.setDetails(details);
210 |
211 | //order.addShipment(new OrderShipment());
212 |
213 | DB.save(order);
214 | return order;
215 | }
216 |
217 | private void createOrder2(Customer customer) {
218 |
219 | Product product1 = Product.find.ref(products.getFirst().getId());
220 |
221 | Order order = new Order(customer);
222 | order.setStatus(Status.SHIPPED);
223 | order.setShipDate(LocalDate.now().plusDays(1));
224 |
225 | List details = new ArrayList<>();
226 | details.add(new OrderDetail(product1, 4, 10.50));
227 | order.setDetails(details);
228 |
229 | //order.addShipment(new OrderShipment());
230 |
231 | DB.save(order);
232 | }
233 |
234 | private void createOrder3(Customer customer) {
235 |
236 | Product product0 = Product.find.ref(products.get(0).getId());
237 | Product product3 = Product.find.ref(products.get(3).getId());
238 |
239 |
240 | Order order = new Order(customer);
241 | order.setStatus(Status.COMPLETE);
242 | order.setShipDate(LocalDate.now().plusDays(2));
243 |
244 | List details = new ArrayList<>();
245 | details.add(new OrderDetail(product0, 3, 10.50));
246 | details.add(new OrderDetail(product3, 40, 2.10));
247 | order.setDetails(details);
248 |
249 | //order.addShipment(new OrderShipment());
250 |
251 | DB.save(order);
252 | }
253 |
254 | private void createOrder4(Customer customer) {
255 |
256 | Order order = new Order(customer);
257 | DB.save(order);
258 | }
259 | }
260 |
--------------------------------------------------------------------------------
/base-example/src/main/module-info.java:
--------------------------------------------------------------------------------
1 | module example.java21 {
2 |
3 | requires io.ebean.postgres;
4 |
5 | opens dbmigration;
6 | exports org.example.domain;
7 | opens org.example.domain;
8 |
9 | provides io.ebean.config.ModuleInfoLoader with org.example.domain._Ebean$ModuleInfo;
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/base-example/src/main/resources/application.yaml:
--------------------------------------------------------------------------------
1 |
2 | ## load external properties
3 | #load:
4 | # properties: ${user.home}/config/my-application.properties
5 | ebean:
6 | dbSchema: ${db.username:sandbox_db}
7 | migration:
8 | run: true
9 | autoCreate: true
10 |
11 | datasource:
12 | db:
13 | username: ${db.username:postgres}
14 | password: ${db.password:postgres}
15 | url: ${db.url:jdbc:postgresql://localhost:6432/sandbox_db}
16 |
--------------------------------------------------------------------------------
/base-example/src/main/resources/dbmigration/model/1.0__initial.model.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/base-example/src/main/resources/ebean.mf:
--------------------------------------------------------------------------------
1 | entity-field-access: true
2 | synthetic: false
3 |
--------------------------------------------------------------------------------
/base-example/src/main/resources/extra-ddl.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | create or replace view order_agg_vw as
7 | select d.order_id as id,
8 | d.order_id as order_id,
9 | sum(d.order_qty * d.unit_price) as order_total,
10 | sum(d.ship_qty * d.unit_price) as ship_total,
11 | sum(d.ship_qty * d.unit_price) as ship_total2
12 | from order_detail d
13 | group by d.order_id;
14 |
15 |
16 |
17 |
18 |
19 | drop view if exists order_agg_vw;
20 |
21 | create view order_agg_vw as
22 | select d.order_id as id,
23 | d.order_id as order_id,
24 | sum(d.order_qty * d.unit_price) as order_total,
25 | sum(d.ship_qty * d.unit_price) as ship_total,
26 | sum(d.ship_qty * d.unit_price) as ship_total2
27 | from order_detail d
28 | group by d.order_id;
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/base-example/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/base-example/src/test/java/main/GenerateDbMigration.java:
--------------------------------------------------------------------------------
1 | package main;
2 |
3 | import io.ebean.annotation.Platform;
4 | import io.ebean.dbmigration.DbMigration;
5 |
6 | /**
7 | * Generate the DB Migration.
8 | */
9 | public class GenerateDbMigration {
10 |
11 | public static void main(String[] args) throws Exception {
12 |
13 | DbMigration dbMigration = DbMigration.create();
14 | dbMigration.setPlatform(Platform.POSTGRES);
15 | // dbMigration.setPathToResources("foo/bar");
16 |
17 | // dbMigration.setAddForeignKeySkipCheck(true);
18 | // dbMigration.setLockTimeout(10);
19 |
20 | // dbMigration.addPlatform(Platform.POSTGRES, "pg");
21 | // dbMigration.addPlatform(Platform.H2, "h2");
22 | // dbMigration.addPlatform(Platform.MYSQL, "mysql");
23 | // dbMigration.addPlatform(Platform.CLICKHOUSE, "ch");
24 |
25 | // generate the migration ddl and xml
26 | // dbMigration.setGeneratePendingDrop("1.3");
27 | dbMigration.generateMigration();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/base-example/src/test/java/main/StartPostgresDocker.java:
--------------------------------------------------------------------------------
1 | package main;
2 |
3 | import io.ebean.test.containers.PostgresContainer;
4 |
5 | public class StartPostgresDocker {
6 |
7 | public static void main(String[] args) {
8 |
9 | PostgresContainer container = PostgresContainer.builder("14")
10 | .dbName("my_app9")
11 | .user("my_app9")
12 | .password("test")
13 | .build();
14 |
15 | System.out.println("url: " + container.jdbcUrl());
16 |
17 | container.startWithDropCreate();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/base-example/src/test/java/org/example/ExampleBaseTestCase.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | //import org.avaje.agentloader.AgentLoader;
4 | //import org.slf4j.Logger;
5 | //import org.slf4j.LoggerFactory;
6 |
7 |
8 | /**
9 | * Used to dynamically load the avaje-ebeanorm-agent.
10 | *
11 | * Alternatives:
12 | * - Use IntelliJ or Eclipse plugins,
13 | * - Rely on maven/ant enhancement (pain in dev, test cycle)
14 | * - Specify the java agent on the command line
15 | *
16 | */
17 | public class ExampleBaseTestCase {
18 |
19 | // protected static Logger logger = LoggerFactory.getLogger(ExampleBaseTestCase.class);
20 | //
21 | // static {
22 | // logger.debug("... preStart");
23 | // if (!AgentLoader.loadAgentFromClasspath("avaje-ebeanorm-agent","debug=1;packages=org.example.**")) {
24 | // logger.info("avaje-ebeanorm-agent not found in classpath - not dynamically loaded");
25 | // }
26 | // }
27 | }
28 |
--------------------------------------------------------------------------------
/base-example/src/test/java/org/example/MyPersonTest.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | import org.assertj.core.api.Assertions;
4 | import org.example.query.QMyPerson;
5 | import org.junit.jupiter.api.Test;
6 |
7 | import static org.assertj.core.api.Assertions.assertThat;
8 |
9 | class MyPersonTest {
10 |
11 | @Test
12 | void insertUpdate() {
13 |
14 | var ma = new MyAddress();
15 | ma.line1 = "line1";
16 | ma.city = "Auckland";
17 |
18 | var mp = new MyPerson();
19 | mp.name = "one";
20 | mp.foo = "foo";
21 | mp.address = ma;
22 | mp.save();
23 |
24 | mp.name = "two";
25 | mp.save();
26 |
27 | MyPerson one = new QMyPerson()
28 | .id.eq(mp.id)
29 | .findOne();
30 |
31 | Assertions.assertThat(one).isNotNull();
32 |
33 | String city = one.address.city;
34 | assertThat(city).isEqualTo("Auckland");
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/base-example/src/test/java/org/example/domain/ContentTest.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import static org.assertj.core.api.Assertions.assertThat;
6 |
7 | public class ContentTest {
8 |
9 |
10 | @Test
11 | public void insert() {
12 |
13 | Content content = new Content("hello");
14 | content.save();
15 |
16 | assertThat(content.getId()).isNotNull();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/base-example/src/test/java/org/example/domain/CustomerTest.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.BeanState;
4 | import io.ebean.DB;
5 | import org.example.ExampleBaseTestCase;
6 | import org.example.domain.query.QCustomer;
7 | import org.junit.jupiter.api.Test;
8 |
9 | import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
10 | import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
11 | import static org.example.domain.query.QCustomer.Alias.id;
12 |
13 | class CustomerTest extends ExampleBaseTestCase {
14 |
15 | /**
16 | * Even though customer name is final Ebean can build a reference
17 | * bean only populating the id property.
18 | */
19 | @Test
20 | void insert() {
21 |
22 | Customer jack = new Customer("Jack");
23 | jack.setPhoneNumber(new PhoneNumber("02134234"));
24 | jack.save();
25 |
26 | // reference bean only has Id populated
27 | Customer refBean = Customer.find.ref(jack.getId());
28 |
29 | // only id property is loaded
30 | BeanState beanState = DB.beanState(refBean);
31 | assertThat(beanState.loadedProps()).containsExactly("id");
32 |
33 | // invoke lazy loading
34 | String name = refBean.getName();
35 | assertThat(name).isEqualTo("Jack");
36 | assertThat(beanState.loadedProps()).contains("id", "name", "version");
37 | }
38 |
39 | @Test
40 | void partialLoad() {
41 |
42 | Customer jim = new Customer("Jim");
43 | jim.setPhoneNumber(new PhoneNumber("234"));
44 | jim.save();
45 |
46 | Customer found = new QCustomer()
47 | .name.equalTo("Jim")
48 | .id.eq(jim.getId())
49 | .select(id)
50 | .findOne();
51 |
52 | assertThat(found).isNotNull();
53 | BeanState beanState = DB.beanState(found);
54 | assertThat(beanState.loadedProps()).containsExactly("id", "contacts", "orders");
55 |
56 | // invoke lazy loading
57 | String name = found.getName();
58 | assertThat(name).isEqualTo("Jim");
59 | assertThat(found.getPhoneNumber().value()).isEqualTo("234");
60 | assertThat(beanState.loadedProps()).contains("id", "name", "inactive");
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/base-example/src/test/java/org/example/domain/ExamplePartialObjectQueryTest.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import org.example.ExampleBaseTestCase;
4 | import org.example.domain.query.QCustomer;
5 | import org.junit.jupiter.api.Assertions;
6 | import org.junit.jupiter.api.Test;
7 |
8 | import java.util.List;
9 |
10 | public class ExamplePartialObjectQueryTest extends ExampleBaseTestCase {
11 |
12 | @Test
13 | public void test() {
14 |
15 | Customer customer = new QCustomer()
16 | .select("name")
17 | .id.eq(12)
18 | .findOne();
19 |
20 | Assertions.assertNotNull(customer);
21 | }
22 |
23 | @Test
24 | public void automaticallyAddJoins() {
25 |
26 | Country nz = Country.find.ref("NZ");
27 |
28 | List customers = new QCustomer()
29 | .billingAddress.country.equalTo(nz)
30 | .select("name")
31 | .findList();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/base-example/src/test/java/org/example/domain/InsertCustomerTest.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.DB;
4 | import io.ebean.Transaction;
5 | import io.ebean.test.LoggedSql;
6 | import org.example.ExampleBaseTestCase;
7 | import org.example.domain.query.QCustomer;
8 | import org.example.service.LoadExampleData;
9 | import org.junit.jupiter.api.Test;
10 |
11 | import java.time.LocalDate;
12 | import java.util.List;
13 | import java.util.UUID;
14 |
15 | import static org.assertj.core.api.Assertions.assertThat;
16 | import static org.junit.jupiter.api.Assertions.assertEquals;
17 | import static org.junit.jupiter.api.Assertions.assertNotNull;
18 |
19 | public class InsertCustomerTest extends ExampleBaseTestCase {
20 |
21 |
22 | @Test
23 | public void test() {
24 |
25 | Customer customer = new Customer("Robin");
26 | customer.setRegistered(LocalDate.of(2014, 4, 1));
27 | customer.getUids().add(UUID.randomUUID());
28 | customer.getUids().add(UUID.randomUUID());
29 | customer.getUids().add(UUID.randomUUID());
30 |
31 | // insert the customer
32 | customer.save();
33 |
34 | final Customer one = new QCustomer()
35 | .id.eq(customer.id)
36 | .forUpdate()
37 | .findOne();
38 |
39 | Customer fetched = Customer.find.byId(customer.getId());
40 |
41 | // fetch using the Ebean singleton style
42 | Customer fetched2 = DB.find(Customer.class, customer.getId());
43 |
44 | assertEquals("Robin", fetched.getName());
45 | assertEquals("Robin", fetched2.getName());
46 | assertEquals(customer.getRegistered(), fetched2.getRegistered());
47 |
48 | fetched2.setRegistered(LocalDate.now().minusDays(3));
49 | fetched2.save();
50 | }
51 |
52 | /**
53 | * Test showing an explicit transaction.
54 | */
55 | @Test
56 | public void testExplicitTransaction() {
57 |
58 | // create a transaction to wrap multiple saves
59 | try (Transaction transaction = DB.beginTransaction()) {
60 |
61 | Customer customer = new Customer("Roberto");
62 | customer.save();
63 |
64 | Customer otherCustomer = new Customer("Franko");
65 | otherCustomer.save();
66 |
67 | transaction.commit();
68 | }
69 | }
70 |
71 |
72 | /**
73 | * Test showing an explicit transaction with extra control
74 | * the use of jdbc batching.
75 | */
76 | @Test
77 | public void testExplicitTransactionWithBatchControls() {
78 |
79 | try (Transaction transaction = DB.beginTransaction()) {
80 |
81 | // turn off cascade persist for this transaction
82 | transaction.setPersistCascade(false);
83 |
84 | // extra control over jdbc batching for this transaction
85 | transaction.setGetGeneratedKeys(false);
86 | transaction.setBatchMode(true);
87 | transaction.setBatchSize(20);
88 |
89 | Customer customer = new Customer("Roberto2");
90 | customer.save();
91 |
92 | transaction.setFlushOnQuery(false);
93 |
94 | Customer otherCustomer = new Customer("Franko2");
95 | otherCustomer.save();
96 |
97 | transaction.commit();
98 | }
99 | }
100 |
101 | @Test
102 | public void testQuery() {
103 |
104 | LoadExampleData.load();
105 |
106 | LoggedSql.start();
107 |
108 | List customers = new QCustomer()
109 | .name.ilike("rob%")
110 | .findList();
111 |
112 | assertNotNull(customers);
113 |
114 | Product p = new Product("ad", "asd");
115 | DB.save(p);
116 |
117 | List sql = LoggedSql.stop();
118 | assertThat(sql).hasSize(2);
119 | assertThat(sql.get(0)).contains("from customer");
120 | assertThat(sql.get(1)).contains("into product");
121 |
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/base-example/src/test/java/org/example/domain/JunkTest.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.FetchGroup;
4 | import io.ebean.annotation.Transactional;
5 | import org.example.domain.query.QCustomer;
6 | import org.example.domain.query.QOrder;
7 | import org.junit.jupiter.api.Test;
8 |
9 | import static org.example.domain.query.QContact.Alias.email;
10 | import static org.example.domain.query.QCustomer.Alias.inactive;
11 | import static org.example.domain.query.QCustomer.Alias.name;
12 | import static org.example.domain.query.QCustomer.Alias.registered;
13 |
14 | public class JunkTest {
15 |
16 | static final FetchGroup fetchGroup = QCustomer.forFetchGroup()
17 | .select(name, inactive, registered)
18 | .contacts.fetch(email)
19 | .buildFetchGroup();
20 |
21 | private final int count;
22 |
23 | JunkTest() {
24 | count = new QOrder()
25 | .findCount();
26 | }
27 | @Test
28 | @Transactional
29 | public void doIt() {
30 |
31 | new QCustomer()
32 | .select(fetchGroup)
33 | .findList();
34 |
35 | System.out.println("here v2");
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/base-example/src/test/java/org/example/domain/LargeQueryWithFindIterateTest.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.annotation.Transactional;
4 | import org.example.ExampleBaseTestCase;
5 | import org.example.domain.query.QCustomer;
6 | import org.junit.jupiter.api.Test;
7 |
8 | import java.util.concurrent.atomic.AtomicLong;
9 |
10 | public class LargeQueryWithFindIterateTest extends ExampleBaseTestCase {
11 |
12 | @Transactional
13 | @Test
14 | public void testFindIterate() {
15 |
16 | // insert 1000 customers
17 | int j = 0;
18 | for (int i = 0; i < 10; i++) {
19 | Customer customer = new Customer("Hello" + j++);
20 | customer.save();
21 | }
22 |
23 |
24 | AtomicLong counter = new AtomicLong();
25 |
26 | new QCustomer()
27 | .id.lessThan(8)
28 | .select("id, name")
29 | .findEach((Customer customer) -> {
30 | long processCount = counter.incrementAndGet();
31 | System.out.println("Hello there2 ... " + customer.getId() + " " + customer.getName() + " counter:" + processCount);
32 | });
33 |
34 |
35 | counter.set(0);
36 |
37 | new QCustomer()
38 | .select("id, name")
39 | .findEachWhile((Customer customer) -> {
40 | long processCount = counter.incrementAndGet();
41 | System.out.println("Hello there2 ... " + customer.getId() + " " + customer.getName() + " counter:" + processCount);
42 | return processCount < 7;
43 | });
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/base-example/src/test/java/org/example/domain/OrderTotalsTest.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.FetchGroup;
4 | import org.example.domain.query.QContact;
5 | import org.example.domain.query.QCustomer;
6 | import org.example.domain.query.QOrder;
7 | import org.example.domain.query.QOrderTotals;
8 | import org.example.service.LoadExampleData;
9 | import org.junit.jupiter.api.Test;
10 |
11 | import java.sql.Timestamp;
12 | import java.time.LocalDate;
13 | import java.util.List;
14 |
15 | import static org.assertj.core.api.Assertions.assertThat;
16 |
17 | public class OrderTotalsTest {
18 |
19 | private static final QCustomer cu = QCustomer.alias();
20 | private static final QContact co = QContact.alias();
21 |
22 | private static final FetchGroup fetchGroup = QCustomer.forFetchGroup()
23 | .select(cu.name, cu.comments)
24 | .contacts.fetch(co.firstName, co.lastName)
25 | .buildFetchGroup();
26 |
27 | @Test
28 | public void basicFind() {
29 |
30 | LoadExampleData.load();
31 |
32 | final List rob = new QCustomer()
33 | .name.startsWith("Rob")
34 | .select(fetchGroup)
35 | .findList();
36 |
37 |
38 | //FetchGroup fg = FetchGroup.of(Customer.class)
39 |
40 |
41 | Address billingAddress = new Address();
42 | billingAddress.setLine1("Not long St");
43 |
44 | Customer jack = new Customer("One");
45 | jack.setBillingAddress(billingAddress);
46 | //
47 | // Contact c0 = new Contact(jack, "a", "b");
48 | // Contact c1 = new Contact(jack, "a", "c");
49 |
50 | jack.save();
51 |
52 |
53 | Country nz = Country.find.ref("NZ");
54 |
55 | int rows = new QCustomer()
56 | .name.startsWith("Rob")
57 | .asUpdate()
58 | .set("registered", LocalDate.now())
59 | .update();
60 |
61 |
62 | new QCustomer()
63 | .alias("cust")
64 | .name.istartsWith("Rob")
65 | .findList();
66 |
67 |
68 | List orderTotals = new QOrderTotals()
69 | .where()
70 | .orderTotal.greaterThan(20)
71 | .findList();
72 |
73 | assertThat(orderTotals).isNotEmpty();
74 | }
75 |
76 | @Test
77 | public void fetchJoin() {
78 |
79 | LoadExampleData.load();
80 |
81 | QOrder o = QOrder.alias();
82 | QCustomer c = QCustomer.alias();
83 |
84 | int rows = new QOrder().findCount();
85 |
86 | List orders = new QOrder()
87 | .select(o.status, o.maxOrderDate, o.totalCount)
88 | .customer.fetch(c.name)
89 | .status.notEqualTo(Order.Status.COMPLETE)
90 | .having()
91 | .totalCount.greaterThan(1)
92 | .findList();
93 |
94 | LocalDate lastWeek = LocalDate.now().minusWeeks(1);
95 |
96 | // select includes aggregation formula
97 | List moreOrders = new QOrder()
98 | .select("status, max(orderDate)")
99 | .status.notEqualTo(Order.Status.NEW)
100 | .findList();
101 |
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/base-example/src/test/java/org/example/domain/ProductTest.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.AcquireLockException;
4 | import io.ebean.DB;
5 | import io.ebean.Query;
6 | import io.ebean.Transaction;
7 | import org.example.domain.query.QProduct;
8 | import org.example.service.LoadExampleData;
9 | import org.junit.jupiter.api.Assertions;
10 | import org.junit.jupiter.api.Disabled;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 | import org.junit.jupiter.api.Test;
14 |
15 | import java.sql.SQLException;
16 | import java.util.List;
17 |
18 | import static org.assertj.core.api.Assertions.assertThat;
19 |
20 | public class ProductTest {
21 |
22 | private static final Logger log = LoggerFactory.getLogger(ProductTest.class);
23 |
24 | @Test
25 | public void findSome() {
26 |
27 | LoadExampleData.load();
28 |
29 | Product product = Product.byName("Computer");
30 |
31 | Assertions.assertNotNull(product);
32 |
33 | List products = new QProduct()
34 | .name.istartsWith("c")
35 | .id.greaterThan(0)
36 | .sku.icontains("c")
37 | .findList();
38 |
39 | Assertions.assertFalse(products.isEmpty());
40 | }
41 |
42 | // Run using Postgres with forUpdateNoWait
43 | @Disabled
44 | @Test
45 | public void checkLockRelease() {
46 |
47 | LoadExampleData.load();
48 |
49 | try (Transaction txn0 = DB.beginTransaction()) {
50 |
51 | Product newProd = new Product("Copper", "COP");
52 | DB.save(newProd);
53 |
54 | List list = new QProduct()
55 | .name.istartsWith("c")
56 | .orderBy()
57 | .name.asc()
58 | .forUpdate()
59 | .findList();
60 |
61 | Product firstProduct = list.getFirst();
62 |
63 | Query queryById = new QProduct()
64 | .id.eq(firstProduct.getId())
65 | .forUpdateNoWait()
66 | .query();
67 |
68 | // Ebean.findNative(Product.class, "select * from product where id = :id for update nowait")
69 | // .setParameter("id", firstProduct.getId());
70 |
71 | assertThat(obtainWithLock(queryById)).isFalse();
72 |
73 | try {
74 | txn0.connection().commit();
75 | //txn0.commitAndContinue();
76 | } catch (SQLException e) {
77 | log.error("Catch exception", e);
78 | }
79 |
80 | assertThat(obtainWithLock(queryById)).isTrue();
81 |
82 | txn0.commit();
83 | }
84 | }
85 |
86 | private boolean obtainWithLock(Query queryById) {
87 | try (Transaction txn = DB.createTransaction()) {
88 | // Apply the transaction and locking to the query
89 | Product product = queryById
90 | .usingTransaction(txn) // Use the transaction
91 | .forUpdate() // Apply the lock
92 | .findOne(); // Fetch the record
93 |
94 | return product != null;
95 |
96 | } catch (AcquireLockException e) {
97 | log.info("Failed to obtain lock {}", e.getMessage());
98 | return false;
99 | }
100 | }
101 |
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/base-example/src/test/java/org/example/domain/TestAggregationTopLevel.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.DB;
4 | import io.ebean.Query;
5 | import io.ebean.test.LoggedSql;
6 | import org.example.domain.query.QDMachineStats;
7 | import org.junit.jupiter.api.BeforeAll;
8 | import org.junit.jupiter.api.Test;
9 |
10 | import java.math.BigDecimal;
11 | import java.time.LocalDate;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | import static org.assertj.core.api.Assertions.assertThat;
16 |
17 | public class TestAggregationTopLevel {
18 |
19 | @BeforeAll
20 | public static void setup() {
21 | loadData();
22 | }
23 |
24 | @Test
25 | public void query_noSelect() {
26 |
27 | Query query = DB.find(DMachineStatsAgg.class)
28 | .where().gt("date", LocalDate.now().minusDays(10))
29 | .query();
30 |
31 | List result = query.findList();
32 | // select t0.date, t0.machine_id from d_machine_stats t0 where t0.date > ?");
33 | assertThat(result).isNotEmpty();
34 | }
35 |
36 | @Test
37 | public void query_machineTotalKms_withHaving() {
38 |
39 | Query query = DB.find(DMachineStatsAgg.class)
40 | .select("machine, date, totalKms, totalCost")
41 | .where().gt("date", LocalDate.now().minusDays(10))
42 | .having().gt("totalCost", 10)
43 | .query();
44 |
45 | List result = query.findList();
46 | // "select t0.machine_id, t0.date, sum(t0.total_kms), sum(cost) from d_machine_stats t0 where t0.date > ? group by t0.machine_id, t0.date having sum(cost) > ?");
47 | assertThat(result).isNotEmpty();
48 | }
49 |
50 | @Test
51 | public void query_machineTotalKms() {
52 |
53 | Query query = DB.find(DMachineStatsAgg.class)
54 | .select("machine, totalKms, totalCost")
55 | .where().gt("date", LocalDate.now().minusDays(10))
56 | .query();
57 |
58 | List result = query.findList();
59 | // "select t0.machine_id, sum(t0.total_kms), sum(cost) from d_machine_stats t0 where t0.date > ? group by t0.machine_id");
60 | assertThat(result).isNotEmpty();
61 | }
62 |
63 | @Test
64 | public void query_byDate() {
65 |
66 | Query query = DB.find(DMachineStatsAgg.class)
67 | .select("date, totalKms, hours, rate, totalCost, maxKms")
68 | .where().gt("date", LocalDate.now().minusDays(10))
69 | .having().gt("hours", 2)
70 | .query();
71 |
72 | List result = query.findList();
73 | // "select t0.date, sum(t0.total_kms), sum(t0.hours), max(t0.rate), sum(cost), max(t0.total_kms) from d_machine_stats t0 where t0.date > ? group by t0.date having sum(t0.hours) > ?");
74 | assertThat(result).isNotEmpty();
75 | }
76 |
77 | @Test
78 | public void groupBy_date_dynamicFormula() {
79 |
80 | LoggedSql.start();
81 |
82 | List result =
83 | new QDMachineStats()
84 | .date.gt(LocalDate.now().minusDays(10))
85 | .select("date, sum(totalKms), sum(hours)")
86 | .havingClause().gt("sum(hours)", 2)
87 | .findList();
88 |
89 | List sql = LoggedSql.stop();
90 |
91 | assertThat(sql).hasSize(1);
92 | assertThat(sql.getFirst()).isNotNull();
93 | assertThat(result).isNotEmpty();
94 | }
95 |
96 | @Test
97 | public void groupBy_MachineAndDate_dynamicFormula() {
98 |
99 | LoggedSql.start();
100 |
101 | List result =
102 | new QDMachineStats()
103 | .select("machine, date, max(rate)")
104 | .date.gt(LocalDate.now().minusDays(10))
105 | .query().having().gt("max(rate)", 4)
106 | .findList();
107 |
108 | List sql = LoggedSql.stop();
109 | assertThat(sql).hasSize(1);
110 | assertThat(sql.getFirst()).isNotNull();
111 | assertThat(result).isNotEmpty();
112 | }
113 |
114 | @Test
115 | public void groupBy_MachineWithJoin_dynamicFormula() {
116 |
117 | Query query = DB.find(DMachineStats.class)
118 | .select("date, max(rate), sum(totalKms)")
119 | .fetchQuery("machine", "name")
120 | .where().gt("date", LocalDate.now().minusDays(10))
121 | .query();
122 |
123 | List result = query.findList();
124 | // "select max(t0.rate), sum(t0.total_kms), t1.id, t1.name from d_machine_stats t0 left join dmachine t1 on t1.id = t0.machine_id where t0.date > ? group by t1.id, t1.name");
125 | assertThat(result).isNotEmpty();
126 | }
127 |
128 | @Test
129 | public void groupBy_MachineDateWithJoin_dynamicFormula() {
130 |
131 | Query query = DB.find(DMachineStats.class)
132 | .select("machine, date, max(rate), sum(totalKms)")
133 | .fetch("machine", "name")
134 | .where().gt("date", LocalDate.now().minusDays(10))
135 | .query();
136 |
137 | List result = query.findList();
138 | // "select t0.date, max(t0.rate), sum(t0.total_kms), t1.id, t1.name from d_machine_stats t0 left join dmachine t1 on t1.id = t0.machine_id where t0.date > ? group by t0.date, t1.id, t1.name");
139 | assertThat(result).isNotEmpty();
140 |
141 | }
142 |
143 | private static void loadData() {
144 |
145 | List machines = new ArrayList<>();
146 |
147 | for (int i = 0; i < 5; i++) {
148 | machines.add(new DMachine("Machine"+i));
149 | }
150 |
151 | DB.saveAll(machines);
152 |
153 | List allStats = new ArrayList<>();
154 |
155 | LocalDate date = LocalDate.now();
156 | for (int i = 0; i < 8; i++) {
157 | for (DMachine machine : machines) {
158 |
159 | DMachineStats stats = new DMachineStats(machine, date);
160 |
161 | stats.setHours(i * 4);
162 | stats.setTotalKms(i * 100);
163 | stats.setCost(BigDecimal.valueOf(i * 50));
164 | stats.setRate(BigDecimal.valueOf(i * 2));
165 |
166 | allStats.add(stats);
167 | }
168 |
169 | date = date.minusDays(1);
170 | }
171 |
172 | DB.saveAll(allStats);
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/base-example/src/test/resources/application-test.yaml:
--------------------------------------------------------------------------------
1 | ebean:
2 | dumpMetricsOnShutdown: true
3 | dumpMetricsOptions: loc,sql,hash
4 | logging:
5 | sql:
6 | comment: false
7 |
8 |
9 | # dbSchema: myapp
10 | # databasePlatformName: sqlserver17
11 | # databasePlatformName: mysql55
12 | test:
13 | # useDocker: false
14 | # shutdown: remove # stop | remove
15 | platform: h2 # h2, postgres, mysql, oracle, sqlserver, sqlite
16 | ddlMode: dropCreate # none | dropCreate | create | migration | createOnly | migrationDropCreate
17 | dbName: sandbox_db
18 | # mysql:
19 | # version: 5.5
20 | # containerName: ms55
21 | # collation: default
22 | # characterSet: utf8mb4
23 |
24 | # postgres:
25 | # extensions: uuid-ossp,hstore,pgcrypto
26 |
27 |
28 | #ebean.foo.ddl:
29 | # generate: true
30 | # run: true
31 | ## initSql: initialise-test-db.sql
32 | ## seedSql: seed-test-db.sql
33 | #
34 | #datasource.foo:
35 | # username: sa
36 | # password: ""
37 | # url: jdbc:h2:mem:tests
38 | # driver: org.h2.Driver
39 |
--------------------------------------------------------------------------------
/base-example/src/test/resources/logback-test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/basic-gradle-java/.gitignore:
--------------------------------------------------------------------------------
1 | out/
2 | build/
3 | generated/
4 | .gradle/
5 | .idea/
6 | *.iml
7 |
--------------------------------------------------------------------------------
/basic-gradle-java/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/basic-gradle-java/README.md:
--------------------------------------------------------------------------------
1 | # example-gradle-java
2 | Show gradle plugin for enhancement and querybean generation
3 |
--------------------------------------------------------------------------------
/basic-gradle-java/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id('idea')
3 | id('java')
4 | id('io.ebean') version '13.11.0'
5 | }
6 |
7 | repositories {
8 | mavenLocal()
9 | mavenCentral()
10 | }
11 |
12 | java {
13 | toolchain {
14 | languageVersion = JavaLanguageVersion.of(17)
15 | }
16 | }
17 |
18 | compileJava {
19 | options.release = 17
20 | options.encoding = 'UTF-8'
21 | }
22 |
23 | dependencies {
24 |
25 | implementation 'org.avaje.composite:logback:1.1'
26 | implementation 'org.postgresql:postgresql:42.5.1'
27 | implementation 'io.ebean:ebean:13.11.0'
28 |
29 | // apt query bean generation
30 | annotationProcessor 'io.ebean:querybean-generator:13.11.0'
31 |
32 | testImplementation 'io.avaje:junit:1.1'
33 | testImplementation 'io.ebean:ebean-test:13.11.0'
34 | }
35 |
36 | test {
37 | useJUnitPlatform()
38 | }
39 |
40 | ebean {
41 | debugLevel = 1 //0 - 9
42 | }
43 |
44 | test {
45 | testLogging.showStandardStreams = true
46 | testLogging.exceptionFormat = 'full'
47 | }
48 |
--------------------------------------------------------------------------------
/basic-gradle-java/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ebean-orm/examples/174c171c6ba1ac6965db6d26b37a304a3172e7ff/basic-gradle-java/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/basic-gradle-java/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/basic-gradle-java/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
84 |
85 | APP_NAME="Gradle"
86 | APP_BASE_NAME=${0##*/}
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | MAX_FD=$( ulimit -H -n ) ||
147 | warn "Could not query maximum file descriptor limit"
148 | esac
149 | case $MAX_FD in #(
150 | '' | soft) :;; #(
151 | *)
152 | ulimit -n "$MAX_FD" ||
153 | warn "Could not set maximum file descriptor limit to $MAX_FD"
154 | esac
155 | fi
156 |
157 | # Collect all arguments for the java command, stacking in reverse order:
158 | # * args from the command line
159 | # * the main class name
160 | # * -classpath
161 | # * -D...appname settings
162 | # * --module-path (only if needed)
163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
164 |
165 | # For Cygwin or MSYS, switch paths to Windows format before running java
166 | if "$cygwin" || "$msys" ; then
167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
169 |
170 | JAVACMD=$( cygpath --unix "$JAVACMD" )
171 |
172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
173 | for arg do
174 | if
175 | case $arg in #(
176 | -*) false ;; # don't mess with options #(
177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
178 | [ -e "$t" ] ;; #(
179 | *) false ;;
180 | esac
181 | then
182 | arg=$( cygpath --path --ignore --mixed "$arg" )
183 | fi
184 | # Roll the args list around exactly as many times as the number of
185 | # args, so each arg winds up back in the position where it started, but
186 | # possibly modified.
187 | #
188 | # NB: a `for` loop captures its iteration list before it begins, so
189 | # changing the positional parameters here affects neither the number of
190 | # iterations, nor the values presented in `arg`.
191 | shift # remove old arg
192 | set -- "$@" "$arg" # push replacement arg
193 | done
194 | fi
195 |
196 | # Collect all arguments for the java command;
197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
198 | # shell script including quotes and variable substitutions, so put them in
199 | # double quotes to make sure that they get re-expanded; and
200 | # * put everything else in single quotes, so that it's not re-expanded.
201 |
202 | set -- \
203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
204 | -classpath "$CLASSPATH" \
205 | org.gradle.wrapper.GradleWrapperMain \
206 | "$@"
207 |
208 | # Use "xargs" to parse quoted args.
209 | #
210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
211 | #
212 | # In Bash we could simply go:
213 | #
214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
215 | # set -- "${ARGS[@]}" "$@"
216 | #
217 | # but POSIX shell has neither arrays nor command substitution, so instead we
218 | # post-process each arg (as a line of input to sed) to backslash-escape any
219 | # character that might be a shell metacharacter, then use eval to reverse
220 | # that process (while maintaining the separation between arguments), and wrap
221 | # the whole thing up as a single "set" statement.
222 | #
223 | # This will of course break if any of these variables contains a newline or
224 | # an unmatched quote.
225 | #
226 |
227 | eval "set -- $(
228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
229 | xargs -n1 |
230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
231 | tr '\n' ' '
232 | )" '"$@"'
233 |
234 | exec "$JAVACMD" "$@"
235 |
--------------------------------------------------------------------------------
/basic-gradle-java/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/basic-gradle-java/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'basic-gradle-java'
2 |
3 |
--------------------------------------------------------------------------------
/basic-gradle-java/src/main/java/org/example/domain/BaseDomain.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import io.ebean.Model;
4 | import io.ebean.annotation.WhenCreated;
5 | import io.ebean.annotation.WhenModified;
6 |
7 | import javax.persistence.Id;
8 | import javax.persistence.MappedSuperclass;
9 | import javax.persistence.Version;
10 | import java.time.Instant;
11 |
12 | @MappedSuperclass
13 | public abstract class BaseDomain extends Model {
14 |
15 | @Id
16 | long id;
17 |
18 | @Version
19 | long version;
20 |
21 | @WhenCreated
22 | Instant whenCreated;
23 |
24 | @WhenModified
25 | Instant whenModified;
26 |
27 | public long getId() {
28 | return id;
29 | }
30 |
31 | public void setId(long id) {
32 | this.id = id;
33 | }
34 |
35 | public long getVersion() {
36 | return version;
37 | }
38 |
39 | public void setVersion(long version) {
40 | this.version = version;
41 | }
42 |
43 | public Instant getWhenCreated() {
44 | return whenCreated;
45 | }
46 |
47 | public void setWhenCreated(Instant whenCreated) {
48 | this.whenCreated = whenCreated;
49 | }
50 |
51 | public Instant getWhenModified() {
52 | return whenModified;
53 | }
54 |
55 | public void setWhenModified(Instant whenModified) {
56 | this.whenModified = whenModified;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/basic-gradle-java/src/main/java/org/example/domain/Customer.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 | import org.example.domain.finder.CustomerFinder;
4 | import io.ebean.annotation.NotNull;
5 |
6 | import javax.persistence.Entity;
7 | import javax.persistence.Lob;
8 | import java.time.LocalDate;
9 |
10 | @Entity
11 | public class Customer extends BaseDomain {
12 |
13 | public static final CustomerFinder find = new CustomerFinder();
14 |
15 | @NotNull
16 | String name;
17 |
18 | LocalDate startDate;
19 |
20 | @Lob
21 | String comments;
22 |
23 | public Customer(String name) {
24 | this.name = name;
25 | }
26 |
27 | public String getName() {
28 | return name;
29 | }
30 |
31 | public void setName(String name) {
32 | this.name = name;
33 | }
34 |
35 | public LocalDate getStartDate() {
36 | return startDate;
37 | }
38 |
39 | public void setStartDate(LocalDate startDate) {
40 | this.startDate = startDate;
41 | }
42 |
43 | public String getComments() {
44 | return comments;
45 | }
46 |
47 | public void setComments(String comments) {
48 | this.comments = comments;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/basic-gradle-java/src/main/java/org/example/domain/finder/CustomerFinder.java:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder;
2 |
3 | import io.ebean.Finder;
4 | import org.example.domain.Customer;
5 | import org.example.domain.query.QCustomer;
6 |
7 | import java.util.Optional;
8 |
9 | public class CustomerFinder extends Finder {
10 |
11 | /**
12 | * Construct using the default Database.
13 | */
14 | public CustomerFinder() {
15 | super(Customer.class);
16 | }
17 |
18 | public Optional byIdOptional(long id) {
19 | return query().setId(id).findOneOrEmpty();
20 | }
21 |
22 | public Customer findByName(String name) {
23 | return
24 | new QCustomer()
25 | .name.eq(name)
26 | .findOne();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/basic-gradle-java/src/test/java/org/example/domain/CustomerTest.java:
--------------------------------------------------------------------------------
1 | package org.example.domain;
2 |
3 |
4 | import org.example.domain.query.QCustomer;
5 | import org.junit.jupiter.api.Test;
6 |
7 | import java.time.LocalDate;
8 | import java.util.Optional;
9 |
10 | import static org.assertj.core.api.Assertions.assertThat;
11 | import static org.junit.jupiter.api.Assertions.*;
12 |
13 |
14 | class CustomerTest {
15 |
16 | @Test
17 | void queryBean() {
18 |
19 | Customer customer = new Customer("Bar");
20 | customer.save();
21 |
22 | Customer found = new QCustomer()
23 | .name.istartsWith("ba")
24 | .findOne();
25 |
26 | System.out.println("found:" + found);
27 | }
28 |
29 | @Test
30 | void saveAndFind() {
31 |
32 | Customer customer = new Customer("hello");
33 | customer.setStartDate(LocalDate.now());
34 | customer.setComments("What is this good for?");
35 | customer.save();
36 |
37 | assertThat(customer.getId()).isGreaterThan(0);
38 |
39 | Optional found = Customer.find.byIdOptional(customer.getId());
40 |
41 | assertTrue(found.isPresent());
42 | found.ifPresent(it -> {
43 | assertEquals(it.getId(), customer.getId());
44 | assertEquals(it.getName(), customer.getName());
45 | }
46 | );
47 |
48 | Customer hello = Customer.find.findByName("hello");
49 | assertThat(hello).isNotNull();
50 |
51 | new QCustomer()
52 | .id.isNotNull()
53 | .findEach(it -> {
54 | System.out.println("hello " + it.getName());
55 | System.out.println(".. started on: " + it.getStartDate());
56 | });
57 |
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/basic-gradle-java/src/test/resources/application-test.yaml:
--------------------------------------------------------------------------------
1 | ebean:
2 | dumpMetricsOnShutdown: true
3 | dumpMetricsOptions: loc,sql,hash #hash,sql,loc
4 | test:
5 | # useDocker: false
6 | # shutdown: stop # stop | remove
7 | platform: h2 # h2, postgres, mysql, oracle, sqlserver, sqlite
8 | ddlMode: dropCreate # none | dropCreate | create | migration | createOnly | migrationDropCreate
9 | dbName: my_gapp
10 |
--------------------------------------------------------------------------------
/basic-gradle-java/src/test/resources/logback-test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | TRACE
5 |
6 |
7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/basic-gradle-java/src/test/resources/old-test.props:
--------------------------------------------------------------------------------
1 |
2 | ## when running tests use H2 and create a new DB
3 |
4 | ebean.dumpMetricsOnShutdown=true
5 | ebean.dumpMetricsOptions=loc #hash,sql,loc
6 |
7 | ebean.ddl.generate=true
8 | ebean.ddl.run=true
9 | ebean.ddl.createOnly=true
10 |
11 | #datasource.default=db
12 |
13 | datasource.db.username=sa
14 | datasource.db.password=
15 | datasource.db.databaseUrl=jdbc:h2:mem:tests
16 | datasource.db.databaseDriver=org.h2.Driver
17 |
18 | #datasource.db.username=unit
19 | #datasource.db.password=unit
20 | #datasource.db.databaseUrl=jdbc:mysql://127.0.0.1:3306/unit
21 | #datasource.db.databaseDriver=com.mysql.jdbc.Driver
22 |
23 | #ebean.docstore.url=http://127.0.0.1:9200
24 | #ebean.docstore.active=true
25 | #ebean.docstore.generateMapping=true
26 | #ebean.docstore.dropCreate=true
27 | #ebean.docstore.create=true
28 |
29 |
30 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | charset = utf-8
7 | end_of_line = lf
8 | indent_size = 2
9 | indent_style = space
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 | spaces_around_operators = true
13 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/.gitignore:
--------------------------------------------------------------------------------
1 | /.gradle/
2 | /build/
3 |
4 | build/
5 | .idea/
6 | .gradle/
7 | *.iml
8 |
9 | classes/
10 | out/
11 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/README.md:
--------------------------------------------------------------------------------
1 | # basic-gradle-kotlin
2 |
3 | Example gradle project
4 | - Gradle 7.4.2
5 | - Kotlin 1.3
6 | - Ebean gradle enhancement plugin
7 | - Kotlin querybean generation using KAPT
8 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id('idea')
3 | id('io.ebean') version '14.6.1'
4 | id('org.jetbrains.kotlin.jvm') version '1.9.23'
5 | id('org.jetbrains.kotlin.kapt') version '1.9.23'
6 | }
7 |
8 | repositories {
9 | mavenLocal()
10 | mavenCentral()
11 | }
12 |
13 | dependencies {
14 |
15 | implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.23'
16 | implementation 'org.avaje.composite:logback:1.1'
17 |
18 | implementation 'io.ebean:ebean:14.6.0'
19 | implementation 'org.postgresql:postgresql:42.7.2'
20 |
21 | kapt 'io.ebean:kotlin-querybean-generator:14.6.0'
22 |
23 | testImplementation 'io.ebean:ebean-test:14.6.0'
24 | testImplementation 'io.avaje:junit:1.1'
25 | }
26 |
27 | test {
28 | useJUnitPlatform()
29 | }
30 |
31 | compileKotlin {
32 | kotlinOptions.jvmTarget = '17'
33 | }
34 |
35 | compileTestKotlin {
36 | kotlinOptions.jvmTarget = '17'
37 | }
38 |
39 | ebean {
40 | debugLevel = 1
41 | }
42 |
43 | test {
44 | testLogging.showStandardStreams = true
45 | testLogging.exceptionFormat = 'full'
46 | }
47 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ebean-orm/examples/174c171c6ba1ac6965db6d26b37a304a3172e7ff/basic-gradle-kotlin/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/basic-gradle-kotlin/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
4 | networkTimeout=10000
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | # This is normally unused
84 | # shellcheck disable=SC2034
85 | APP_BASE_NAME=${0##*/}
86 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
147 | # shellcheck disable=SC3045
148 | MAX_FD=$( ulimit -H -n ) ||
149 | warn "Could not query maximum file descriptor limit"
150 | esac
151 | case $MAX_FD in #(
152 | '' | soft) :;; #(
153 | *)
154 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
155 | # shellcheck disable=SC3045
156 | ulimit -n "$MAX_FD" ||
157 | warn "Could not set maximum file descriptor limit to $MAX_FD"
158 | esac
159 | fi
160 |
161 | # Collect all arguments for the java command, stacking in reverse order:
162 | # * args from the command line
163 | # * the main class name
164 | # * -classpath
165 | # * -D...appname settings
166 | # * --module-path (only if needed)
167 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
168 |
169 | # For Cygwin or MSYS, switch paths to Windows format before running java
170 | if "$cygwin" || "$msys" ; then
171 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
172 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
173 |
174 | JAVACMD=$( cygpath --unix "$JAVACMD" )
175 |
176 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
177 | for arg do
178 | if
179 | case $arg in #(
180 | -*) false ;; # don't mess with options #(
181 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
182 | [ -e "$t" ] ;; #(
183 | *) false ;;
184 | esac
185 | then
186 | arg=$( cygpath --path --ignore --mixed "$arg" )
187 | fi
188 | # Roll the args list around exactly as many times as the number of
189 | # args, so each arg winds up back in the position where it started, but
190 | # possibly modified.
191 | #
192 | # NB: a `for` loop captures its iteration list before it begins, so
193 | # changing the positional parameters here affects neither the number of
194 | # iterations, nor the values presented in `arg`.
195 | shift # remove old arg
196 | set -- "$@" "$arg" # push replacement arg
197 | done
198 | fi
199 |
200 | # Collect all arguments for the java command;
201 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
202 | # shell script including quotes and variable substitutions, so put them in
203 | # double quotes to make sure that they get re-expanded; and
204 | # * put everything else in single quotes, so that it's not re-expanded.
205 |
206 | set -- \
207 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
208 | -classpath "$CLASSPATH" \
209 | org.gradle.wrapper.GradleWrapperMain \
210 | "$@"
211 |
212 | # Stop when "xargs" is not available.
213 | if ! command -v xargs >/dev/null 2>&1
214 | then
215 | die "xargs is not available"
216 | fi
217 |
218 | # Use "xargs" to parse quoted args.
219 | #
220 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
221 | #
222 | # In Bash we could simply go:
223 | #
224 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
225 | # set -- "${ARGS[@]}" "$@"
226 | #
227 | # but POSIX shell has neither arrays nor command substitution, so instead we
228 | # post-process each arg (as a line of input to sed) to backslash-escape any
229 | # character that might be a shell metacharacter, then use eval to reverse
230 | # that process (while maintaining the separation between arguments), and wrap
231 | # the whole thing up as a single "set" statement.
232 | #
233 | # This will of course break if any of these variables contains a newline or
234 | # an unmatched quote.
235 | #
236 |
237 | eval "set -- $(
238 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
239 | xargs -n1 |
240 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
241 | tr '\n' ' '
242 | )" '"$@"'
243 |
244 | exec "$JAVACMD" "$@"
245 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo.
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48 | echo.
49 | echo Please set the JAVA_HOME variable in your environment to match the
50 | echo location of your Java installation.
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo.
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62 | echo.
63 | echo Please set the JAVA_HOME variable in your environment to match the
64 | echo location of your Java installation.
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/settings.gradle:
--------------------------------------------------------------------------------
1 | //pluginManagement {
2 | // repositories {
3 | // mavenLocal()
4 | // gradlePluginPortal()
5 | // }
6 | //}
7 | rootProject.name = 'basic-gradle-kotlin'
8 |
9 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/kotlin/org/example/domain/Animal.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain
2 |
3 | import jakarta.persistence.Entity
4 | import jakarta.persistence.ManyToOne
5 |
6 | @Entity
7 | class Animal(name: String, owner: Owner) : BaseModel() {
8 |
9 | var name :String = name
10 |
11 | @ManyToOne
12 | var owner: Owner = owner
13 |
14 | var age : Int = 0
15 | var type : String? = null
16 |
17 | var notes: String? = null
18 | }
19 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/kotlin/org/example/domain/BaseModel.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain
2 |
3 | import io.ebean.Model
4 | import io.ebean.annotation.WhenCreated
5 | import io.ebean.annotation.WhenModified
6 | import java.time.Instant
7 | import jakarta.persistence.Id
8 | import jakarta.persistence.MappedSuperclass
9 | import jakarta.persistence.Version
10 |
11 | @MappedSuperclass
12 | open class BaseModel : Model() {
13 |
14 | @Id
15 | var id: Long = 0
16 |
17 | @Version
18 | var version: Long = 0
19 |
20 | @WhenCreated
21 | lateinit var whenCreated: Instant
22 |
23 | @WhenModified
24 | lateinit var whenModified: Instant
25 | }
26 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/kotlin/org/example/domain/Customer.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain
2 |
3 | import io.ebean.annotation.Length
4 | import org.example.domain.finder.CustomerFinder
5 | import java.math.BigDecimal
6 | import jakarta.persistence.Column
7 | import jakarta.persistence.Entity
8 | import jakarta.persistence.OneToMany
9 |
10 | @Entity
11 | open class Customer(name: String) : BaseModel() {
12 |
13 | @Column(length = 150, unique = true)
14 | var name: String = name
15 |
16 | var creditLimit: BigDecimal? = null
17 |
18 | @Length(500)
19 | var notes: String? = null
20 |
21 | @OneToMany(mappedBy = "customer")
22 | var orders : List = mutableListOf()
23 |
24 | companion object Find : CustomerFinder()
25 | }
26 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/kotlin/org/example/domain/Order.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain
2 |
3 | import org.example.domain.finder.OrderFinder
4 | import java.time.OffsetDateTime
5 | import jakarta.persistence.*
6 |
7 | @Entity
8 | @Table(name="orders")
9 | class Order(customer: Customer) : BaseModel() {
10 |
11 | @ManyToOne
12 | val customer: Customer = customer
13 |
14 | var whenPlacedFor : OffsetDateTime? = null
15 |
16 | var whenInvoiced : OffsetDateTime? = null
17 |
18 | @OneToMany(cascade = [CascadeType.ALL], mappedBy = "order")
19 | var lines: MutableList = mutableListOf()
20 |
21 | companion object Find : OrderFinder()
22 | }
23 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/kotlin/org/example/domain/OrderLine.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain
2 |
3 | import org.example.domain.finder.OrderLineFinder
4 | import jakarta.persistence.Entity
5 | import jakarta.persistence.ManyToOne
6 |
7 | @Entity
8 | class OrderLine(
9 |
10 | @ManyToOne
11 | var product: Product,
12 |
13 | var quantity: Int
14 |
15 | ) : BaseModel() {
16 |
17 | @ManyToOne(optional = false)
18 | var order: Order? = null
19 |
20 | var description: String? = null
21 |
22 |
23 | companion object Find : OrderLineFinder()
24 | }
25 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/kotlin/org/example/domain/Owner.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain
2 |
3 | import jakarta.persistence.Entity
4 |
5 | @Entity
6 | class Owner(name:String) : BaseModel() {
7 |
8 | val name :String = name
9 |
10 | var phone:String? = null
11 | }
12 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/kotlin/org/example/domain/Product.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain
2 |
3 | import io.ebean.annotation.Length
4 | import org.example.domain.finder.ProductFinder
5 | import jakarta.persistence.Entity
6 |
7 | @Entity
8 | class Product(
9 |
10 | @Length(20)
11 | var sku: String,
12 |
13 | @Length(100)
14 | var name: String
15 |
16 | ) : BaseModel() {
17 |
18 | companion object Find : ProductFinder()
19 | }
20 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/kotlin/org/example/domain/finder/CustomerFinder.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder
2 |
3 | import io.ebean.Finder
4 | import org.example.domain.Customer
5 | import org.example.domain.query.QCustomer
6 |
7 | open class CustomerFinder : Finder(Customer::class.java) {
8 |
9 | fun findByName(name: String): Customer? {
10 |
11 | val c = QCustomer._alias
12 |
13 | return QCustomer()
14 | .select(c.id, c.name)
15 | .name.istartsWith(name)
16 | .findOne()
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/kotlin/org/example/domain/finder/OrderFinder.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder
2 |
3 | import io.ebean.Finder
4 | import org.example.domain.Order
5 |
6 | open class OrderFinder : Finder(Order::class.java)
7 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/kotlin/org/example/domain/finder/OrderLineFinder.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder
2 |
3 | import io.ebean.Finder
4 | import org.example.domain.OrderLine
5 |
6 | open class OrderLineFinder : Finder(OrderLine::class.java)
7 |
8 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/kotlin/org/example/domain/finder/ProductFinder.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain.finder
2 |
3 | import io.ebean.Finder
4 | import org.example.domain.Product
5 |
6 | open class ProductFinder : Finder(Product::class.java) {
7 |
8 | fun findMapBySku() : Map {
9 |
10 | return query()
11 | .setMapKey("sku")
12 | .findMap()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/kotlin/org/example/service/HelloService.kt:
--------------------------------------------------------------------------------
1 | package org.example.service
2 |
3 | import org.example.domain.Order
4 | import org.example.domain.query.QOrder
5 |
6 | class HelloService {
7 |
8 | fun findAll(): MutableList {
9 | return QOrder()
10 | .version.isNotNull
11 | .findList()
12 | }
13 |
14 | fun findSome() {
15 | val one = QOrder()
16 | .version.gt(1)
17 | .findOne()
18 |
19 | val i = one?.customer?.orders?.size ?: 0;
20 | println(i)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/resources/dbmigration/1.0__initial.sql:
--------------------------------------------------------------------------------
1 | -- apply changes
2 | create table animal (
3 | id bigint generated by default as identity not null,
4 | name varchar(255) not null,
5 | owner_id bigint not null,
6 | age integer not null,
7 | type varchar(255),
8 | notes varchar(255),
9 | version bigint not null,
10 | when_created timestamptz not null,
11 | when_modified timestamptz not null,
12 | constraint pk_animal primary key (id)
13 | );
14 |
15 | create table customer (
16 | id bigint generated by default as identity not null,
17 | name varchar(150) not null,
18 | credit_limit decimal(16,3),
19 | notes varchar(500),
20 | version bigint not null,
21 | when_created timestamptz not null,
22 | when_modified timestamptz not null,
23 | constraint uq_customer_name unique (name),
24 | constraint pk_customer primary key (id)
25 | );
26 |
27 | create table orders (
28 | id bigint generated by default as identity not null,
29 | customer_id bigint not null,
30 | when_placed_for timestamptz,
31 | when_invoiced timestamptz,
32 | version bigint not null,
33 | when_created timestamptz not null,
34 | when_modified timestamptz not null,
35 | constraint pk_orders primary key (id)
36 | );
37 |
38 | create table order_line (
39 | id bigint generated by default as identity not null,
40 | product_id bigint not null,
41 | quantity integer not null,
42 | order_id bigint not null,
43 | description varchar(255),
44 | version bigint not null,
45 | when_created timestamptz not null,
46 | when_modified timestamptz not null,
47 | constraint pk_order_line primary key (id)
48 | );
49 |
50 | create table owner (
51 | id bigint generated by default as identity not null,
52 | name varchar(255) not null,
53 | phone varchar(255),
54 | version bigint not null,
55 | when_created timestamptz not null,
56 | when_modified timestamptz not null,
57 | constraint pk_owner primary key (id)
58 | );
59 |
60 | create table product (
61 | id bigint generated by default as identity not null,
62 | sku varchar(20) not null,
63 | name varchar(100) not null,
64 | version bigint not null,
65 | when_created timestamptz not null,
66 | when_modified timestamptz not null,
67 | constraint pk_product primary key (id)
68 | );
69 |
70 | create index ix_animal_owner_id on animal (owner_id);
71 | alter table animal add constraint fk_animal_owner_id foreign key (owner_id) references owner (id) on delete restrict on update restrict;
72 |
73 | create index ix_orders_customer_id on orders (customer_id);
74 | alter table orders add constraint fk_orders_customer_id foreign key (customer_id) references customer (id) on delete restrict on update restrict;
75 |
76 | create index ix_order_line_product_id on order_line (product_id);
77 | alter table order_line add constraint fk_order_line_product_id foreign key (product_id) references product (id) on delete restrict on update restrict;
78 |
79 | create index ix_order_line_order_id on order_line (order_id);
80 | alter table order_line add constraint fk_order_line_order_id foreign key (order_id) references orders (id) on delete restrict on update restrict;
81 |
82 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/main/resources/dbmigration/model/1.0__initial.model.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/test/kotlin/main/GenerateDbMigration.kt:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import io.ebean.annotation.Platform
4 | import io.ebean.dbmigration.DbMigration
5 |
6 | fun main() {
7 |
8 | val dbMigration = DbMigration.create()
9 | dbMigration.setPlatform(Platform.POSTGRES)
10 |
11 | dbMigration.generateMigration()
12 | }
13 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/test/kotlin/org/example/domain/AnimalTest.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain
2 |
3 | import org.example.domain.query.QAnimal
4 | import org.junit.jupiter.api.Test
5 |
6 |
7 | class AnimalTest {
8 |
9 | @Test
10 | fun setName() {
11 |
12 | val allie = Owner("Allie")
13 | allie.phone = "021777890"
14 | allie.save()
15 |
16 | val ethan = Owner("Ethan")
17 | ethan.phone = "021354879"
18 | ethan.save()
19 |
20 |
21 | val pepper = Animal("pepper", allie)
22 | pepper.age = 2
23 | pepper.notes = "squashed by garage door"
24 | pepper.type = "cat"
25 | pepper.save()
26 |
27 | val foo = Animal("coloso", ethan)
28 | foo.age = 5
29 | foo.type = "bunny"
30 | foo.notes = "saw paw"
31 | foo.save()
32 |
33 | // val foofoo
34 | val animals = QAnimal()
35 | //.name.startsWith("pe")
36 | .or()
37 | .owner.name.istartsWith("a")
38 | .owner.name.istartsWith("e")
39 | .endOr()
40 | .age.lessThan(9)
41 | .findList()
42 |
43 | println("found ${animals.size} animals")
44 |
45 | for (animal in animals) {
46 | println("found ${animal.name} ${animal.age} ${animal.type} v${animal.version} owner:${animal.owner.name}${animal.owner.phone}")
47 | }
48 |
49 | // pepper.name="allie"
50 | pepper.save()
51 |
52 | // foo.name="ethan"
53 | foo.save()
54 |
55 |
56 | val other = QAnimal()
57 | .type.isIn("cat", "bunny")
58 | .notes.isNotNull
59 | .id.lessThan(3)
60 | .findList()
61 |
62 | println("Second query size: ${other.size}")
63 |
64 | for (animal in other) {
65 | println(" ${animal.name} ${animal.notes} id:${animal.id} v${animal.version} ${animal.owner.name}")
66 | }
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/test/kotlin/org/example/domain/CustomerTest.kt:
--------------------------------------------------------------------------------
1 | package org.example.domain
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.example.domain.query.QCustomer
5 | import org.example.domain.query.QOrder
6 | import org.junit.jupiter.api.Test
7 | import java.math.BigDecimal
8 | import org.example.domain.query.QCustomer.Companion._alias as c
9 | import org.example.domain.query.QOrder.Companion._alias as or
10 |
11 | class CustomerTest {
12 |
13 | private val fetchGroup = QCustomer.forFetchGroup()
14 | .select(c.name, c.creditLimit)
15 | .orders.fetch(or.id, or.version)
16 | .buildFetchGroup()
17 |
18 | @Test
19 | fun someQuery() {
20 |
21 | val customers = QCustomer()
22 | .select(fetchGroup)
23 | .name.eqOrNull("Rob")
24 | .creditLimit.gt(30_000)
25 | // .orders.isNotEmpty()
26 | .findList()
27 |
28 | assertThat(customers).isEmpty()
29 | }
30 |
31 | @Test
32 | fun save() {
33 |
34 | setup()
35 |
36 | val customer = QCustomer()
37 | .select(c.name)
38 | .name.eq("Rob")
39 | .findOne()
40 |
41 | customer?.orders?.size
42 | val nm = customer?.name ?: "asd"
43 |
44 | val customerEmpty = QCustomer()
45 | .select(c.name)
46 | .name.eq("Rob")
47 | .findOneOrEmpty()
48 |
49 | customerEmpty.ifPresent {
50 | println(it.name)
51 | }
52 |
53 | val rob = Customer.findByName("Rob") ?: throw IllegalStateException("no rob")
54 |
55 | assertThat(rob.name).isEqualTo("Rob")
56 |
57 | val products = Product.findMapBySku()
58 |
59 | val order = Order(rob)
60 |
61 | order.lines.add(OrderLine(products["DK1"]!!, 7))
62 | order.lines.add(OrderLine(products["DK2"]!!, 20))
63 | order.lines.add(OrderLine(products["CH3"]!!, 1))
64 |
65 | order.save()
66 |
67 | val foundOrder = QOrder()
68 | .customer.name.startsWith("Ro")
69 | .findOne()
70 |
71 | assertThat(foundOrder?.customer?.name).isEqualTo("Rob")
72 | }
73 |
74 | private fun setup() {
75 |
76 | Product("DK1", "Desk").save()
77 | Product("DK2", "Desk 2").save()
78 | Product("CH3", "Chair 3").save()
79 |
80 | val customer = Customer("Rob")
81 | customer.creditLimit = BigDecimal("1000")
82 | customer.save()
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/test/kotlin/org/example/service/HelloServiceTest.kt:
--------------------------------------------------------------------------------
1 | package org.example.service
2 |
3 | import org.assertj.core.api.Assertions.assertThat
4 | import org.example.domain.query.QOrder
5 | import org.junit.jupiter.api.Test
6 |
7 | internal class HelloServiceTest {
8 |
9 | @Test
10 | fun findAll() {
11 |
12 | val service = HelloService()
13 |
14 | QOrder().delete()
15 |
16 | val list = service.findAll()
17 | assertThat(list).isEmpty()
18 |
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/test/resources/application-test.yaml:
--------------------------------------------------------------------------------
1 | ebean:
2 | # dumpMetricsOnShutdown: true
3 | # dumpMetricsOptions: loc,sql,hash,w50 #hash,sql,loc
4 | test:
5 | # useDocker: false
6 | # shutdown: stop # stop | remove
7 | platform: h2 # h2, postgres, mysql, oracle, sqlserver, sqlite
8 | ddlMode: dropCreate # none | dropCreate | create | migration | createOnly | migrationDropCreate
9 | dbName: mykt_app
10 |
--------------------------------------------------------------------------------
/basic-gradle-kotlin/src/test/resources/logback-test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | TRACE
5 |
6 |
7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------