Skip to content

Commit

Permalink
Adds support for using MonetaryAmount in @ElementCollection #652
Browse files Browse the repository at this point in the history
  • Loading branch information
nikola.malenic authored and vladmihalcea committed Oct 12, 2023
1 parent 9d5f167 commit 4a3d394
Show file tree
Hide file tree
Showing 17 changed files with 2,376 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package io.hypersistence.utils.hibernate.type.money;

import io.hypersistence.utils.hibernate.util.AbstractPostgreSQLIntegrationTest;
import org.hibernate.annotations.Columns;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.javamoney.moneta.Money;
import org.junit.Test;

import javax.money.MonetaryAmount;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertEquals;

/**
* @author Nikola Malenic
*/
public class MySQLMonetaryAmountTypeElementCollectionTest extends AbstractPostgreSQLIntegrationTest {
@Override
protected Class<?>[] entities() {
return new Class[]{
Salary.class
};
}

@Test
public void testPersistAndReadMoney() {
Salary _salary = doInJPA(entityManager -> {
Salary salary = new Salary();
salary.getComponents().add(new SalaryComponent(Money.of(new BigDecimal("10.23"), "USD")));

entityManager.persist(salary);

return salary;
});

doInJPA(entityManager -> {
Salary salary = entityManager.find(Salary.class, _salary.getId());

assertEquals(salary.getComponents().get(0).getValue(), Money.of(new BigDecimal("10.23"), "USD"));
});
}

@Test
public void testSearchByMoneyInElementCollection() {
doInJPA(entityManager -> {
Salary salary1 = new Salary();
salary1.getComponents().add(new SalaryComponent(Money.of(new BigDecimal("10.23"), "USD")));
salary1.getComponents().add(new SalaryComponent(Money.of(new BigDecimal("20.23"), "USD")));
entityManager.persist(salary1);

Salary salary2 = new Salary();
salary2.getComponents().add(new SalaryComponent(Money.of(new BigDecimal("30.23"), "EUR")));
entityManager.persist(salary2);
});

doInJPA(entityManager -> {
Money money = Money.of(new BigDecimal("10.23"), "USD");
Salary salary = entityManager.createQuery("select s from Salary s join s.components sc where sc.value = :salary", Salary.class)
.setParameter("salary", money)
.getSingleResult();

assertEquals(1, salary.getId());
});
}

@Entity(name = "Salary")
@Table(name = "salary")
public static class Salary {
@Id
@GeneratedValue
private long id;

private String other;

@ElementCollection
private List<SalaryComponent> components = new ArrayList<>();

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public List<SalaryComponent> getComponents() {
return components;
}

public String getOther() {
return other;
}

public void setOther(String other) {
this.other = other;
}
}

@Embeddable
@TypeDef(name = "monetary-amount-currency", typeClass = MonetaryAmountType.class, defaultForType = MonetaryAmount.class)
public static class SalaryComponent {
@Columns(columns = {
@Column(name = "salary_amount"),
@Column(name = "salary_currency")
})
@Type(type = "monetary-amount-currency")
private MonetaryAmount value;

public SalaryComponent(MonetaryAmount value) {
this.value = value;
}

public SalaryComponent() {

}

public MonetaryAmount getValue() {
return value;
}

public void setValue(MonetaryAmount value) {
this.value = value;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package io.hypersistence.utils.hibernate.type.money;

import io.hypersistence.utils.hibernate.util.AbstractPostgreSQLIntegrationTest;
import org.hibernate.annotations.Columns;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.javamoney.moneta.Money;
import org.junit.Test;

import javax.money.MonetaryAmount;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.List;

import static org.junit.Assert.assertEquals;

/**
* @author Nikola Malenic
*/
public class MySQLMonetaryAmountTypeEmbeddedTest extends AbstractPostgreSQLIntegrationTest {
@Override
protected Class<?>[] entities() {
return new Class[]{
Salary.class
};
}

@Test
public void testReadAndWrite() {
Salary _salary = doInJPA(entityManager -> {
Salary salary = new Salary();
salary.setEmbeddedSalary(new EmbeddableMonetaryAmount(Money.of(new BigDecimal("10.23"), "USD")));

entityManager.persist(salary);

return salary;
});

doInJPA(entityManager -> {
Salary salary = entityManager.find(Salary.class, _salary.getId());

assertEquals(salary.getEmbeddedSalary().amount, Money.of(new BigDecimal("10.23"), "USD"));
});

Salary salary = doInJPA(entityManager -> {
return entityManager.find(Salary.class, _salary.getId());
});

salary.setEmbeddedSalary(new EmbeddableMonetaryAmount(Money.of(new BigDecimal("10.49"), "USD")));

doInJPA(entityManager -> {
entityManager.merge(salary);
});
}

@Test
public void testSearchByMoney() {
doInJPA(entityManager -> {
Salary salary1 = new Salary();
salary1.setEmbeddedSalary(new EmbeddableMonetaryAmount(Money.of(new BigDecimal("10.23"), "USD")));
entityManager.persist(salary1);

Salary salary2 = new Salary();
salary2.setEmbeddedSalary(new EmbeddableMonetaryAmount((Money.of(new BigDecimal("20.23"), "EUR"))));
entityManager.persist(salary2);
});

doInJPA(entityManager -> {
Money money = Money.of(new BigDecimal("10.23"), "USD");
Salary salary = entityManager.createQuery("select s from Salary s where s" +
".embeddedSalary.amount = :amount", Salary.class)
.setParameter("amount", money)
.getSingleResult();

assertEquals(1, salary.getId());
});
}

@Test
public void testSearchByComponents() {
doInJPA(entityManager -> {
Salary salary1 = new Salary();
salary1.setEmbeddedSalary(new EmbeddableMonetaryAmount((Money.of(new BigDecimal("10.23"), "USD"))));
entityManager.persist(salary1);

Salary salary2 = new Salary();
salary2.setEmbeddedSalary(new EmbeddableMonetaryAmount((Money.of(new BigDecimal("20.23"), "EUR"))));
entityManager.persist(salary2);
});

doInJPA(entityManager -> {
BigDecimal amount = BigDecimal.TEN;
List<Salary> salaries = entityManager.createQuery("select s from Salary s where s.embeddedSalary.amount.amount >= :amount", Salary.class)
.setParameter("amount", amount)
.getResultList();


assertEquals(1L, salaries.get(0).getId());
assertEquals(2L, salaries.get(1).getId());
});

doInJPA(entityManager -> {
String currency = "USD";
Salary salary = entityManager.createQuery("select s from Salary s where s.embeddedSalary.amount.currency = :currency", Salary.class)
.setParameter("currency", currency)
.getSingleResult();

assertEquals(1L, salary.getId());
});
}

@Entity(name = "Salary")
@Table(name = "salary")
public static class Salary {
@Id
@GeneratedValue
private long id;

private String other;

@Embedded
private EmbeddableMonetaryAmount embeddedSalary;

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public EmbeddableMonetaryAmount getEmbeddedSalary() {
return embeddedSalary;
}

public void setEmbeddedSalary(EmbeddableMonetaryAmount embeddedSalary) {
this.embeddedSalary = embeddedSalary;
}

public String getOther() {
return other;
}

public void setOther(String other) {
this.other = other;
}
}

@Embeddable
@TypeDef(name = "monetary-amount-currency", typeClass = MonetaryAmountType.class, defaultForType = MonetaryAmount.class)
public static class EmbeddableMonetaryAmount {
@Columns(columns = {
@Column(name = "salary_amount"),
@Column(name = "salary_currency")
})
@Type(type = "monetary-amount-currency")
private MonetaryAmount amount;

public EmbeddableMonetaryAmount(MonetaryAmount amount) {
this.amount = amount;
}

public EmbeddableMonetaryAmount() {

}


public MonetaryAmount getAmount() {
return amount;
}

public void setAmount(MonetaryAmount amount) {
this.amount = amount;
}
}
}
Loading

0 comments on commit 4a3d394

Please sign in to comment.