SpringBoot – 3 (Thymeleaf)

Selamlar, bu yazımızda Thymeleaf ‘den bahsedeceğim. Spring ile entegresini yapıp bir kaç özelliğini kullanacağım. Thymeleaf, açık kaynak olarak geliştirilen, Servlet tabanlı çalışan bir template engine‘ dir. Daha önce eğer JSP kullanarak bir şeyler yaptıysanız Thymeleaf veya benzeri FreeMarker, Apache Velocity gibi diğer template engine‘lerin  avantajlarını daha iyi anlayabilirsiniz. Ön yüzde  size gerçekten esneklik sağlamakta.  Buradan daha detaylı bilgi alabilirsiniz. Şimdi SpringBoot ile entegresine geçelim. İlk önce bağımlılığımızı ekleyelim. (Bu yazımda da daha önceki projemden ilerliyorum.)

pom.xml

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Ardından resources klasörü içindeki templates klasörüne index.html dosyamızı ekleyelim.

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Thymeleaf Examples</title>
</head>
<body>
Test
</body>
</html>

Sonrasında HomeController sınıfımızı aşağıdaki gibi düzenleyelim.

HomeController.java

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Created by ufuk on 8.8.2016.
 */
@Controller
public class HomeController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String displayHomePage(Model model) {

        return "index";
    }
}

Controller‘daki metodumuz da olusturduğumuz html dosyanın adını return ediyoruz. Ardından projeyi run edip http://localhost:8080/SpringGiris/ istek yaptığımızda index.html dosyamızın içeriği gelmektedir. Bu kadar kolay işte 🙂 Şimdi basit olarak for, if ve attribute yazdıralım ekrana.

Controller sınıfımızı düzenleyelim.

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Created by ufuk on 8.8.2016.
 */
@Controller
public class HomeController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String displayHomePage(Model model) {

        List<String> uuids = getUUIDList(10);

        model.addAttribute("list", uuids);
        model.addAttribute("isEmpty", uuids.isEmpty());
        model.addAttribute("fullName", "Ufuk Halis");

        return "index";
    }

    private List<String> getUUIDList(int limit) {
        List<String> uuids = new ArrayList<>();
        for (int i = 0; i < limit; i++) {
            uuids.add(UUID.randomUUID().toString());
        }
        return uuids;
    }
}

Rastgele değerler üretip bir liste oluşturdum. Daha sonra bu listeyi ve başka değerleri Metodumuzun model parametresine addAttribute şeklinde ekledik. Artık View kısmından bu değerlere ulaşabiliriz. index.html dosyamızı da düzenlersek.

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>Thymeleaf Examples</title>
</head>
<body>
<h1 th:text="'Full Name : ' + ${fullName}"></h1>

<h1>UUIDS</h1>
<p th:each="item : ${list}" th:text="${item}"></p>

<p th:if="${isEmpty}" >Empty</p>
<p th:if="${!isEmpty}" >Not Empty</p>

</body>
</html>

Evet, controller da set ettiğimiz attribute‘lere ulaşıp ekrana bastık, each ile listemiz içinde döndük, if ile de koşul durumunu gördük. Thymeleaf ‘in bu özelliklerini JSP kodlarken JSTL ile de yapabiliriz. Ancak tabi Thymeleaf ‘in ayıran özelliklerini fragment‘lar, SpringSecurity ile olan ilişkisi, hazır metotları vb. özelliklerini ilerleyen yazılarda zamanı geldikçe değineceğim. Şimdilik bu kadar. 🙂

Ya İyi Olarak Ölürsün, ya da kötüye dönüşecek kadar uzun yaşarsın
(The Dark Knight – 2008)

Advertisements

SprinBoot – 2 (Hibernate)

Merhaba, bu yazımızda SpringBoot veritabanı işlemleri ile devam edeceğiz. Önceki yazımdaki projeyi kullanacağım. SpringBoot ile veritabanı ayarları sizde görünce hak vereceksiniz oldukça kolay.

Yazımda Hibernate falan üzerinde çok durmayacağımdan o yüzden entity sınıflarındaki notasyonların hepsini açıklamayacağım. Belki hibernate için ayrı bir yazıda anlatabilirim. Bu yazımdaki amaç SpringBoot ile bu işlemleri yapmak.

Örneğimizde User ve Address adında iki entity sınıfımız olacak ve uygulama ayağı kalkma anında veritabanımıza kayıtlar ekleyip okuyup sonrasında sileceğiz.
Öncelikle pom.xml dosyamıza gerekli bağımlılıkları ekleyelim.

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <scope>runtime</scope>
</dependency>

Veritabanı olarak ben MySQL kullanıyorum. Siz herhangi bir veritabanı kullanabilirsiniz. Ona göre connector bağımlılığınızı eklemeniz gerekir.

Ardından application.properties dosyamızı gerekli eklemeleri yapalım.

spring.datasource.url = jdbc:mysql://localhost:3306/boot_hibernate_db
spring.datasource.username = root
spring.datasource.password = root
# Keep the connection alive if idle for a long time (needed in production)
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
# Show or not log for each sql query
spring.jpa.show-sql = false

# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = create-drop
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

Evet, veritabanı yolumuzu, kullanıcı adı ve parola bilgilerini, Spring jpa ile ilgili ayarlarımızı bu şekilde yapabiliyoruz. Ardından User ve Address entity ‘lerimiz ekleyelim. Entity notasyonu ile etiketlenen sınıflar Hibernate tarafından tablo olarak dönüştürülür. Sınıf elemanları da kolon olarak dönüştürülür.  Bizim User ile Address arasında OneToMany ilişkisi olacak, bir kullanıcının birden fazla adresi olabilir anlamına geliyor bu da.

User.java

import javax.persistence.*;
import java.io.Serializable;
import java.util.List;

/**
 * Created by ufuk on 10.8.2016.
 */
@Entity
public class User implements Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String firstName;
    private String middleName;
    private String lastName;

    @OneToMany(mappedBy = "user")
    private List<Address> addresses;

    public void setAddresses(List<Address> addresses) {
        this.addresses = addresses;
    }

    public List<Address> getAddresses() {
        return addresses;
    }

    public long getId() {
        return id;
    }

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

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getMiddleName() {
        return middleName;
    }

    public void setMiddleName(String middleName) {
        this.middleName = middleName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

Address.java

import javax.persistence.*;
import java.io.Serializable;

/**
 * Created by ufuk on 10.8.2016.
 */
@Entity
public class Address implements Serializable{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String address;
    @ManyToOne
    @JoinColumn(name = "user")
    private User user;

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

    public long getId() {
        return id;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getAddress() {
        return address;
    }
}


Projeyi bu haliyle çalıştırdığımızda gerekli tablolar belirttiğimiz veritabanında oluşacaktır. Şimdi ise Repository interface‘lerimizi oluşturalım. Repository interface‘lerimiz sayesinde CRUD işlemlerini gerçekleştireceğiz.

UserRepository.java

import com.ufuk.entity.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by ufuk on 10.8.2016.
 */
@Repository
@Transactional
public interface UserRepository extends CrudRepository<User, Long> {
}

AddressRepository.java

import com.ufuk.entity.Address;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by ufuk on 10.8.2016.
 */
@Repository
@Transactional
public interface AddressRepository extends CrudRepository<Address, Long> {
}

Evet görüldüğü gibi Repository notasyonu ile etiketleyip CrudRepository sınıfından extend ediyoruz.

Ardından Main sınıfımızı düzenleyelim.

SpringBootGirisApplication.java
import com.ufuk.entity.Address;
import com.ufuk.entity.User;
import com.ufuk.repository.AddressRepository;
import com.ufuk.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.Arrays;

@SpringBootApplication
public class SpringBootGirisApplication implements CommandLineRunner{

   @Autowired
   UserRepository userRepository;

   @Autowired
   AddressRepository addressRepository;

   public static void main(String[] args) {
      SpringApplication.run(SpringBootGirisApplication.class, args);
   }


   @Override
   public void run(String... strings) throws Exception {
      Address address = new Address();
      address.setAddress("Arlington Street, 1578");

      User user = new User();
      user.setFirstName("Ufuk");
      user.setLastName("Halis");
      user.setAddresses(Arrays.asList(addressRepository.save(address)));
      user = userRepository.save(user);

      readData();

      userRepository.delete(user);

      readData();

   }

   private void readData() {
      Iterable<User> userIterable = userRepository.findAll();
      if (!userIterable.iterator().hasNext()) {
         System.out.println("No data found!");
      }
      for (User u : userIterable) {
         System.out.println("First Name : " + u.getFirstName());
         System.out.println("Last Name : " + u.getLastName());
         for (Address a : u.getAddresses()) {
            System.out.println("Address : " + a.getAddress());
         }
         System.out.println("*******************************");
      }
   }
}

Evet, görüldüğü gibi basit olarak bir kullanıcı ve adres ekledik, okuduk ve sildik ve bunu yarattığımız Repository sınıflarıyla yapabildik. Repository sınıflarımıza kendi metot gövdelerimizi ekleyebiliriz. Örneğin bir kullanıcıyı firstName alanına göre bulmak istersek şu şekilde bir metot gövdesi eklememiz yeterli.

User findByFirstName(String firstName);

Spring Data metot isminden gerekli sorguyu yapacak ve sonucu döndürecektir. Custom query oluşturmak için de metodumuzu Query notasyonu ile etiketlemek yeterli. Ardından içine query‘imizi yazabiliriz.

Uygulamayı çalıştırdığımızda aşağıdaki ekran görüntüsü gibi bir çıktı alacağız.Ekran Alıntısı.PNG

Evet, bu yazımızda bu kadar. Basit olarak SpringBoot ile bir veritabanına bağlandık, kayıt sildik ekledik vs.  Sonraki yazılarda görüşmek üzere…

Bu ve bundan sonraki yazıları filmlerden alıntılar ile bitireceğim artık, kullandığım bitiriş cümlesi çok beğenilmedi arkadaşlar tarafından 🙂

-Kaşığı eğmeyi boşa deneme. Bu imkansızdır. Bunun yerine sadece gerçeği anlamaya çalış.Tamam mı?
-Gerçek nedir?
-Aslında bir kaşık yok. Eğilen sadece kendinsin.
(Matrix)