First we need to add all dependecies to project in pom.xml :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
after that we will create the @SpringBootApplication class :
@SpringBootApplication
public class ExampleApplication {
private static final Logger logger = LoggerFactory.getLogger(ExampleApplication.class);
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}
then we have to create the model objects :
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "NAME", length = 64)
private String name;
@OneToMany(cascade = CascadeType.ALL
, mappedBy = "customer", fetch = FetchType.EAGER, orphanRemoval = true
)
private List<Order> orders;
@Version
private Long version;
.......
@Entity
@Table(name = "ORDERS")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne
@JoinColumn(name="CUSTOMER_ID")
private Customer customer;
@Column(name = "ORDER_NAME", length = 128)
private String orderName;
@Version
private Long version;
due to the fact that order is a reserved word in sql, is better to change the tabe name to "ORDERS".
Also we are using @OneToMany(cascade = CascadeType.ALL , mappedBy = "customer", fetch = FetchType.EAGER, orphanRemoval = true), take care when using FetchType.EAGER, it is possible to load entire database in memmory, if you are not taking care of using it, be default JPA is using LAZY, but on this example to keep things simple i used EAGER.
Each entity had a field with @Version , just to see what happens with this when we are changing a order.
On ExampleApplication we will define a CommandLineRunner bean :
@Bean
public CommandLineRunner exampleRunner(CustomerRepository customerRepository) {
return (args) -> {
Customer customer = new Customer("Customer 1", new ArrayList<>());
customer.getOrders().add(new Order(customer, "order 1"));
customer.getOrders().add(new Order(customer, "order 2"));
customerRepository.save(customer);
customerRepository.findAll().forEach(c -> {
logger.info(c.toString());
});
// The output 1 :
//Customer{id=1, name='Customer 1', version=0, orders=[Order{id=1, orderName='order 1', version=0}, Order{id=2, orderName='order 2', version=0}]
final Iterable<Customer> customers = customerRepository.findAll();
customers.forEach(c -> {
c.getOrders().forEach(order -> {
order.setOrderName(order.getOrderName() + "1");
});
customerRepository.save(c);
});
customerRepository.findAll().forEach(c -> {
logger.info(c.toString());
});
// The output 2 :
//Customer{id=1, name='Customer 1', version=0, orders=[Order{id=1, orderName='order 11', version=1}, Order{id=2, orderName='order 21', version=1}]}
customer = customerRepository.findOne(customer.getId());
customer.setName(customer.getName() + "1");
customerRepository.save(customer);
customerRepository.findAll().forEach(c -> {
logger.info(c.toString());
});
// The output 3 :
//Customer{id=1, name='Customer 11', version=1, orders=[Order{id=1, orderName='order 11', version=1}, Order{id=2, orderName='order 21', version=1}]}
};
}
As you can see on first output the version is 0 for all enitites, after changin the order name the version is changed only on those entities and on final optul after we changed the cutomer its version is updated to 1
Download sources from git : sources
Category: Java Tutorials