简体   繁体   中英

Update database record using Java Spring JPA and crud

Trying to learn Java Spring by creating a simple project for storing football teams. I am storing data to a database using JPA. Currently i can save a "Team" to my database with my logged in user. Now i wish to update the record for cases where team is changed or user makes mistake etc.

Can someone help me and provide the best approach?

1 Team Model class

@Data
@Entity
@Table(name="User_Team")
public class Team implements Serializable {

@OneToOne
private User user;

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;

@NotBlank(message="Team Name is required")
private  String teamName;

@NotBlank(message="Location is required")
private  String location;

@NotBlank(message="Nickname required")
private String nickName;

private String yearEstablished;


public Sport sport;

private Divison divison;

  }   

2. Team Repository

@Repository
public interface TeamRepository extends CrudRepository<Team, Long> {
Team findAllById(Long id);

   }

3. Team Controller

@Slf4j
@Controller
@RequestMapping("/team")
@SessionAttributes("Team")

public class TeamController {

private TeamRepository teamRepository;

public TeamController(TeamRepository teamRepository) {
    this.teamRepository = teamRepository;
}

@Autowired
TeamRepository service;

@PostMapping
public String processOrder(@Valid Team team, Errors errors,
                           SessionStatus sessionStatus,
                           @AuthenticationPrincipal User user) {

    if (errors.hasErrors()) {
        return "team";
    }

    team.setUser(user);

    service.save(team);
    sessionStatus.setComplete();

    return "redirect:/team";
}


   @GetMapping
    public String displayTeam(Model model) {

      model.addAttribute("team", service.findAll());

    return "/team";
  }
  }

4. Team Html

 <!DOCTYPE html>
 <!--suppress ALL -->
 <html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:th="http://www.thymeleaf.org">
 <head>
 <title>Team</title>
 <link rel="stylesheet" th:href="@{/styles.css}" />
 </head>
 <body>
 <div class="hero-image">
<div class="hero-text">
    <h1 style="font-size:50px">Team</h1>
</div>
</div>


<div class="tab">

<button class="tablinks"><a href="team">Team Info</a></button>
<button class="tablinks"><a href="player">Players Info</a></button>
<button class="tablinks"><a href="fixtures">Fixtures</a></button>

</div>

<div id="Home" class="tabcontent">
<h3>Home</h3>
</div>

<div id="About" class="tabcontent">
<h3>Team Info</h3>
</div>

 <div id="Contact" class="tabcontent">
   <h3>Player Info</h3>
 </div>

<table>
    <tr>
        <th>Team name</th>
        <th>Location</th>
        <th>Nickname</th>
        <th>Year Formed</th>
        <th>Sport</th>
        <th>Division</th>
    </tr>
    <tr th:each = "about: ${team}">
        <td th:text="${about.teamName}"></td>
        <td th:text="${about.location}"></td>
        <td th:text="${about.nickName}"></td>
        <td th:text="${about.yearEstablished}"></td>
        <td th:text="${about.sport}"></td>
        <td th:text="${about.divison.displayValue}"></td>

    </tr>

    <!--<input type="file" name="pic" accept="image/*">
    <input type="submit">-->

</table>




 <button class="open-button" onclick="openForm()">Add your team</button>
 <div class="form-popup" id="myForm">
 <form method="POST" th:action="@{/team}" class="form-container" id="aboutForm">
    <label for="teamName">Team name: </label>
    <input type="text" name="teamName"/><br/>

    <label for="location">Location: </label>
    <input type="text" name="location"/><br/>

    <label for="nickName">Nickname: </label>
    <input type="text" name="nickName"/><br/>

    <label for="yearEstablished">Year Formed: </label>
    <input type="text" name="yearEstablished"/><br/>


    <label for="sport">Sport:</label>
    <select name="sport">
        <option th:each="colorOpt : ${T(sportsapp.sportsapp.Sport).values()}"
                th:value="${colorOpt}" th:text="${colorOpt.displayName}"></option>
    </select>


    <label for="divison">Divison:</label>
    <select name="divison">
        <option th:each="colorOpt : ${T(sportsapp.sportsapp.Divison).values()}"
                th:value="${colorOpt}" th:text="${colorOpt.displayValue}"></option>
    </select>


    <div class="mytest">
        <input type="submit" value="Add"/>
    </div>
    <input type="button" class="btn cancel" onclick="closeForm()" value="Close"/>

    </form>
    </div>
 <script>
  function openForm() {
    document.getElementById("myForm").style.display = "block";
  }

  function closeForm() {
    document.getElementById("myForm").style.display = "none";
  }
</script>



 </body>
 </html>

TeamRepository has a method save().

With the method save() you can both create & update a class Object. In case the object exists it will update it, in case the object does not exists it will create it.

In short modify the object you want and save it like :

public void updateTeam(Team k) {
        this.service.save(k);
    }

EDIT

The full process of interacting with a database & a front-end is up to your preference. There are a lot of different ways to achieve this but I personally use this way to make things work :

@Entity
@Table(name = "user", catalog = "filesystem", schema = "")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "User.findAll", query = "SELECT u FROM User u")
    , @NamedQuery(name = "User.findByName", query = "SELECT u FROM User u WHERE u.name = :name")
    , @NamedQuery(name = "User.findByJobTitle", query = "SELECT u FROM User u WHERE u.jobTitle = :jobTitle")
    , @NamedQuery(name = "User.findByMail", query = "SELECT u FROM User u WHERE u.mail = :mail")
    , @NamedQuery(name = "User.findByDateRegisted", query = "SELECT u FROM User u WHERE u.dateRegisted = :dateRegisted")
    , @NamedQuery(name = "User.findByDateActivated", query = "SELECT u FROM User u WHERE u.dateActivated = :dateActivated")
    , @NamedQuery(name = "User.findByActive", query = "SELECT u FROM User u WHERE u.active = :active")})
public class User implements Serializable, UserDetails {

    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(columnDefinition = "BINARY(16)", name = "unique_id", updatable = false, nullable = false)
    @ApiModelProperty(notes = "UUID format.") //swagger attribute level configuration (discription)
    private UUID uniqueId;

    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 155)
    @Column(name = "name")
    private String name;

    @Basic(optional = true)
    @Size(min = 1, max = 155)
    @Column(name = "jobTitle")
    private String jobTitle;

    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 155)
    @Column(name = "mail")
    private String mail;

    @Basic(optional = true)
    @Column(name = "date_registed")
    @Temporal(TemporalType.TIMESTAMP)
    private Date dateRegisted;

    @Column(name = "date_activated")
    @Temporal(TemporalType.TIMESTAMP)
    private Date dateActivated;

    @Basic(optional = true)
    @Column(name = "active")
    private short active;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "userId", fetch = FetchType.LAZY)
    private UserToken userToken;

    public User() {
    }

    public User(UUID uniqueId) {
        this.uniqueId = uniqueId;
    }

    public User(UUID uniqueId, String name, String jobTitle, String mail, Date dateRegisted, short active) {
        this.uniqueId = uniqueId;
        this.name = name;
        this.jobTitle = jobTitle;
        this.mail = mail;
        this.dateRegisted = dateRegisted;
        this.active = active;
    }

    public User(UserProfile_MGR user_model) {
        this.uniqueId = UUID.fromString(user_model.getId());
        this.name = user_model.getDisplayName();
        this.jobTitle = user_model.getJobTitle();
        this.mail = user_model.getMail();
        this.dateRegisted = new Date();
        this.active = 1;
    }
    public User(com.microsoft.graph.models.extensions.User user) {
        this.uniqueId = UUID.fromString(user.id);
        this.name = user.displayName;
        this.jobTitle = user.jobTitle;
        this.mail = user.mail;
        this.dateRegisted = new Date();
        this.active = 1;
    }

    public UUID getUniqueId() {
        return uniqueId;
    }

    public void setUniqueId(UUID uniqueId) {
        this.uniqueId = uniqueId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getJobTitle() {
        return jobTitle;
    }

    public void setJobTitle(String jobTitle) {
        this.jobTitle = jobTitle;
    }

    public String getMail() {
        return mail;
    }

    public void setMail(String mail) {
        this.mail = mail;
    }

    public Date getDateRegisted() {
        return dateRegisted;
    }

    public void setDateRegisted(Date dateRegisted) {
        this.dateRegisted = dateRegisted;
    }

    public Date getDateActivated() {
        return dateActivated;
    }

    public void setDateActivated(Date dateActivated) {
        this.dateActivated = dateActivated;
    }

    public short getActive() {
        return active;
    }

    public void setActive(short active) {
        this.active = active;
    }

    public UserToken getUserToken() {
        return userToken;
    }

    public void setUserToken(UserToken userToken) {
        this.userToken = userToken;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (uniqueId != null ? uniqueId.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof User)) {
            return false;
        }
        User other = (User) object;
        if ((this.uniqueId == null && other.uniqueId != null) || (this.uniqueId != null && !this.uniqueId.equals(other.uniqueId))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "com.usermanagement.api.entity.User[ uniqueId=" + uniqueId + " ]";
    }

    //    JWT Essential information
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return new ArrayList<>();
    }

    @Override
    @JsonIgnore
    public String getPassword() {
        return this.uniqueId.toString();
    }

    @Override
    @JsonIgnore
    public String getUsername() {
        return this.name;
    }

    @Override
    @JsonIgnore
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    @JsonIgnore
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    @JsonIgnore
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return ((this.active == 0) ? false : true);
    }

}

Next the CRUD repository, note that the CRUD repository impolements the basic interaction methods by default such as save, delete, select etc. If you need something more advanced you can create namedQueries on your entity and "enable" them on your CRUD interface :

public interface UserRepositoryInterface extends CrudRepository<User, UUID> {
    public List<User> findByMail(String mail);
}

Next You have the repository which implements or Autowireds the CRUD Inteface :

@Repository
public class UserRepository {

    @Autowired
    private UserRepositoryInterface userRepository;

    public List<User> findUsers() {
        Iterable<User> source = userRepository.findAll();
        List<User> target = new ArrayList<>();
        source.forEach(target::add);
        return target;
    }

    public User findUser(UUID uuid) throws UserNotFound {
        Optional<User> user = userRepository.findById(uuid);
        if (!user.isPresent()) {
            throw new UserNotFound("We where not able to identify the user resource.");
        }
        return user.get();
    }

    public User createUser(User user) throws UserAlreadyExistsException {
        try {
            this.findUser(user.getUniqueId());
            throw new UserAlreadyExistsException("User Allready Exists in the Database");
        } catch (UserNotFound ex) {
            userRepository.save(user);
        }
        return user;
    }

    public void updateUserProfile(User user) throws UserNotFound {
        if (findUser(user.getUniqueId()).getUniqueId() == null) {
            throw new UserNotFound("User did not found.");
        }
        userRepository.save(user);
    }

    public void deleteUserById(UUID uuid) throws UserNotFound {
        User user = findUser(uuid);
        userRepository.deleteById(user.getUniqueId());
    }

}

You can Autowired the repository on a @Service or directly to your @RestController Rsource up to you :

@RestController
@RequestMapping("/users")
public class UserResource {

    @Autowired
    private UserRepository userRepository;

    //retrieveAllUsers
    @RequestMapping(method = RequestMethod.GET, path = "/")
    public Iterable<User> findAllUsers() {
        return userRepository.findUsers();
    }


    //Delete /users/{id}
    @RequestMapping(method = RequestMethod.DELETE, path = "/users/{uuid}")
    public ResponseEntity<Object> deleteUserById(@PathVariable UUID uuid) throws UserNotFound {
        userRepository.deleteUserById(uuid);
        return ResponseEntity.status(200).body(new Message("ok"));
    }
}

Finally the method I use to interact with my services is this plain js like :

function base_Get_request(url,callback) {
    let xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            callback(xhr.response);
        }
    }
    xhr.open('GET', url, true);
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.send();
}

Where the URL is the URL of the service I want to consume and the callback is the function that will be called on success a short template could be this :

 function tempCallback(data){
    let temp =  JSON.parse(data);
console.log(temp)
  }

Hope it helps.

在这里可以找到一个很好的例子,它涵盖了我的请求: https : //www.baeldung.com/spring-boot-crud-thymeleaf

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM