I Have two models, One is used to store user details and with that Id, I'm trying to save the user location in another table, which uses the same id of the user as the primary key.
User Model
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(unique = true)
private String username;
#Column(unique=true)
private String email;
private String password;
private String Role;
#OneToOne(mappedBy = "user")
private UserLocation location;
//...constructors, getters and setters
}
UserLocation Model
#Entity
public class UserLocation {
#Id
private Long id;
#OneToOne(cascade = CascadeType.MERGE)
#JoinColumn(name="id")
#MapsId
private User user;
private Point location;
//...constructors, getters and setters
}
My Spring Boot Application class where I try to insert records to both the table
#SpringBootApplication
public class ContainmentZoneAlertApp implements CommandLineRunner {
#Autowired
private UserlocationRepository userLocRepo;
#Autowired
private UserRepository userRepo;
public static void main(String[] args) {
SpringApplication.run(ContainmentZoneAlertApp.class, args);
}
#Override
public void run(String... args) throws Exception {
UserLocation userLocation = new UserLocation();
Geometry geometry = GeometryUtil.wktToGeometry(String.format("POINT (13.0827 80.2707)"));
//GeometryUtil is a utility class
User user = new User(null,"user 3","user3#gmail.com","hello123","user");
user = userRepo.save(user);
userLocation.setUser(user);
userLocation.setLocation((Point)geometry);
userLocRepo.save(userLocation);
}
}
Im getting
caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.saravanan.models.User
Why am I getting this error? and what does persist mean? & I'm using MySQL database
You have to make sure that both save operations are in the same transaction otherwise the first entity is detached an this leads to this exception.
So simply add #Transactional to the run method:
#Transactional
#Override
public void run(String... args) throws Exception {
Related
I'm using Spring MVC with Spring data.
Simple example of my problem:
My dao Service class:
#Service
#AllArgsConstructor
#Transactional
public class FooService{
private FooRepository fooRepo;
public Foo save(Foo foo){
return fooRepo.save(foo);
}
}
and controller:
#Controller
#AllArgsConstructor
#Transactional //if I remove this, method add does not save a foo.
//But I don't understand why, because FooService already has #Transactional annotation
public class FooController{
private FooService fooService;
#PostMapping("/add")
public String add(#RequestParam("programName") String programName, #RequestParam("id") long id){
Foo foo = fooService.findById(id).get();
foo.setProgramName(programName);
fooService.save(foo);
return "somePage";
}
}
If I remove #Transaction annotation from controller class, method save will not update foo object.
And I don't understand why I should mark controller by #Transactional annotation if I already mark service class by this annotation?
############ UPDATE ####################
Simple detailed description:
I have Program and Education entities. One Program has many Education, Education entity has foreign key program_id.
There is a page with Program form, there are fields: program id, program theme,..., and field with a list of education id separated by commas.
I'm trying to update the education list at the program, so I add a new education id at the page form and click save. Through debugger I see, that new education has appeared in the program, but changes do not appear in the database.
#Controller
#RequestMapping("/admin/program")
#AllArgsConstructor //this is lombok, all services autowired by lombok with through constructor parameters
#Transactional//if I remove this, method add does not save a foo.
//But I don't understand why, because FooService already has #Transactional annotation
public class AdminProgramController {
private final ProgramService programService;
private final EducationService educationService;
#PostMapping("/add")
public String add(#RequestParam("themeName") String themeName, #RequestParam("orderIndex") int orderIndex,
#RequestParam(value = "educationList", defaultValue = "") String educationList,
#RequestParam(value = "practicalTestId") long practicalTestId){
saveProgram(themeName, orderIndex, educationList, practicalTestId);
return "adminProgramAdd";
private Program saveProgram(long programId, String themeName, int orderIndex, String educationList, long practicalTestId){
List<Long> longEducationList = Util.longParseEducationList(parsedEducationList); //this is list of Education id separeted by commas that I load from page form
//creating new program and set data from page form
Program program = new Program();
program.setId(programId);
program.setThemeName(themeName);
program.setOrderIndex(orderIndex);
//starting loop by education id list
longEducationList.stream()
.map(educationRepo::findById)
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(edu->{
//linking program and education
program.getEducationList().add(edu);
edu.setProgram(program);
});
//saving new program or updating by service if there is one already
Program savedProgram = programService.save(program);
//saving education with updated program
for(Education edu : savedProgram.getEducationList())
{
educationService.save(edu);
}
return savedProgram;
}
}
ProgramService:
#Service
#AllArgsConstructor //this is lombok, all services autowired by lombok with throught constructor parameters
#Transactional
public class ProgramService {
private ProgramRepo programRepo;
//other code here.....
public Program save(Program program) {
Optional<Program> programOpt = programRepo.findById(program.getId());
//checking if the program is already exist, then update it paramateres
if(programOpt.isPresent()){
Program prgm = programOpt.get();
prgm.setThemeName(program.getThemeName());
prgm.setOrderIndex(program.getOrderIndex());
prgm.setPracticalTest(program.getPracticalTest());
prgm.setEducationList(program.getEducationList());
return programRepo.save(prgm);
}
//if not exist then just save new program
else{
return programRepo.save(program);
}
}
}
Education service
#Service
#AllArgsConstructor //this is lombok, all services autowired by lombok with throught constructor parameters
#Transactional
public class EducationService {
private EducationRepo educationRepo;
//other code here....
public Education save(Education education){
return educationRepo.save(education);
}
}
Program entity:
#Entity
#ToString(exclude = {"myUserList", "educationList", "practicalTest"})
#Getter
#Setter
#NoArgsConstructor
public class Program implements Comparable<Program>{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "theme_name")
private String themeName;
#Column(name = "order_index")
private int orderIndex; //from 1 to infinity
#OneToMany(mappedBy = "program", fetch = FetchType.LAZY)
#OrderBy("orderIndex asc")
private List<Education> educationList = new ArrayList<>();
#OneToMany(mappedBy = "program", fetch = FetchType.LAZY)
private List<MyUser> myUserList = new ArrayList<>();
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "test_id")
private PracticalTest practicalTest;
public Program(int orderIndex, String themeName) {
this.orderIndex = orderIndex;
this.themeName = themeName;
}
public Program(long id) {
this.id = id;
}
//other code here....
}
Education entity:
#Entity
#ToString(exclude = {"program", "myUserList"})
#Getter
#Setter
#NoArgsConstructor
public class Education implements Comparable<Education>{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String link;
#Column(name = "order_index")
private int orderIndex;
private String type;
private String task;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "program_id")
private Program program;
#OneToMany(mappedBy = "education", fetch = FetchType.LAZY)
private List<MyUser> myUserList = new ArrayList<>();
public Education(String link, int orderIndex, String task, Program program) {
this.link = link;
this.orderIndex = orderIndex;
this.task = task;
this.program = program;
}
//other code here....
}
Program repo:
#Repository
public interface ProgramRepo extends CrudRepository<Program, Long> {
Optional<Program> findByPracticalTest(PracticalTest practicalTest);
Optional<Program> findByOrderIndex(int orderIndex);
List<Program> findByIdBetween(long start, long end);
}
Education repo:
#Repository
public interface EducationRepo extends CrudRepository<Education, Long> {
Optional<Education> findByProgramAndOrderIndex(Program program, int orderIndex);
#Query("select MAX(e.orderIndex) from Education e where e.program.id = ?1")
int findLastEducationIndexByProgramId(long programId);
}
I think the problem is program object created in one transaction and saved in another. That's why if I put Transactional on controller it works. There are two ways to solve the problem:
Without transactional on the controller: then I must save education object at first, because it has program id field and then save the program object.
With transactional on controller: then saving order has no matter, because saving object occurs in one transaction
This is Project Entity which is used as reference by other entities in my project :
#Entity
#Data
#RequiredArgsConstructor
#AllArgsConstructor
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
#NonNull private String projectName;
#NonNull private String projectCode;
#NonNull private String description;
#NonNull private Integer resourceSize;
//other fields
}
Another two Entities Roster and OutsourceRequestForm which copies fields projectName and resourceSize from Project Entity upon creation.
#Entity
#Data
#RequiredArgsConstructor
#AllArgsConstructor
public class Roster {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
#Version
private Long version;
#NonNull private String projectName;
#NonNull private Integer resourceSize;
//other fields
}
#Entity
#RequiredArgsConstructor
#Data
public class OutsourceRequestForm {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
#Version
private Long version;
#NonNull private String projectName;
#NonNull private Integer resourceSize;
//other fields
}
Change to field resourceSize needs to be reflected in above two entities as well.
Here is logic for that in service class updating/inserting project entities.
#Service
public class ProjectServiceImpl implements ProjectService {
#Autowired ProjectRepository projectRepo;
#Autowired ProjectWebClientService projectWebClientService;
#Autowired RosterService rosterService;
#Autowired OutsourceRequestFormService orfService;
/**
*
*/
public void updateProjectData() {
//delete existing records
projectRepo.deleteAll();
//fetch data from other server
List<Project> projectList = projectWebClientService.getProjectData();
//save project data
projectRepo.save(projectList);
// ----> need solution for below part <----
projectList.forEach(project-> {
//find rosters by projectName and update resourceSize
rosterService.updateRoster(project.getProjectName() , project.getResourceSize());
//find orf by projectName and update resourceSize
orfService.updateOrf(project.getProjectName() , project.getResourceSize());
});
}
}
Is there any way i can remove this part projectList.forEach {} from this class and do it at some other location in a better way as It is violating single responsibility principle ?
It will also maintain Single Responsibility Principle. and You can omit the loop as well. But there is an issue in this every time you update project, it will work (if this is requirement then it is fine).
Please try this:-
#Entity
#Data
#RequiredArgsConstructor
#AllArgsConstructor
**#EntityListeners({RosterListener.class ,OrfListener.class})**
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
#NonNull private String projectName;
#NonNull private String projectCode;
#NonNull private String description;
#NonNull private Integer resourceSize;
//other fields
}
Listener:-
import javax.persistence.PostUpdate;
public class RosterListener{
#PostUpdate
void onProjectUpdate(Project roject) {
RosterService rosterService = (RosterService ) BeanUtility.getBean("RosterService "); // find this as from your application context environment
osterService.updateRoster(project.getProjectName(), project.getResourceSize());
}
}
import javax.persistence.PostUpdate;
public class OrfListener{
#PostUpdate
void onProjectUpdate(Project roject) {
OutsourceRequestFormService outsourceRequestFormService = (OutsourceRequestFormService ) BeanUtility.getBean("outsourceRequestFormService "); // find this as from your application context environment
outsourceRequestFormService.updateOrf(project.getProjectName(), project.getResourceSize());
}
}
I was trying to implement bi-directional relationships bettwen my entities.
Student
#Table(name = "students")
#Entity
public class Student {
#Id
// #GeneratedValue(strategy = GenerationType.AUTO)
private long album;
#NotNull
private String name;
#NotNull
private String surname;
#OneToMany(mappedBy = "student", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH})
private List<StudentSection> studentSections;
#Transactional(propagation=Propagation.REQUIRED, readOnly=true, noRollbackFor=Exception.class)
public void addSection(Section section){
if(this.studentSections == null){
this.studentSections = new ArrayList<>();
}
StudentSection studentSectionToAdd = new StudentSection();
studentSectionToAdd.setStudent(this);
studentSectionToAdd.setSection(section);
this.studentSections.add(studentSectionToAdd); //here
section.addStudentSection(studentSectionToAdd);
}
}
the connecting entity in a ManyToMany relationship
#Table(name = "student_section")
#Entity
public class StudentSection {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Integer grade;
private Date date;
#NotNull
#ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH})
#JoinColumn(name = "student_id")
private Student student;
#NotNull
#ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH})
#JoinColumn(name = "section_id")
private Section section;
}
and Section
#Table(name = "sections")
#Entity
public class Section {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#NotNull
private String name;
#NotNull
private Integer sizeOfSection;
#NotNull
private Boolean isActive;
#OneToMany(mappedBy = "section", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH})
private List<StudentSection> studentSections;
void addStudentSection(StudentSection studentSection){
if(this.studentSections == null){
this.studentSections = new ArrayList<>();
}
this.studentSections.add(studentSection);
}
}
I ran into a problem with the Student.addSection() method. When trying to execute it I got an error on the this.studentSections.add(studentSectionToAdd); line, saying
failed to lazily initialize a collection of role: Student.studentSections, could not initialize proxy - no Session
I read about it and found out that the best way to fix this is to add the #Transactional annotation to the method, however it didnt change anything and I cant get it to work.
I also tried moving the Student.addSection() method to
StudentServiceImpl
#Service
#Primary
public class StudentServiceImpl implements StudentService {
protected StudentRepository studentRepository;
#Autowired
public StudentServiceImpl(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}
#Override
#Transactional(propagation = Propagation.REQUIRED, readOnly = true, noRollbackFor = Exception.class)
public void addSection(Student student, Section section) {
if (student.getStudentSections() == null) {
student.setStudentSections(new ArrayList<>());
}
StudentSection studentSectionToAdd = new StudentSection();
studentSectionToAdd.setStudent(student);
studentSectionToAdd.setSection(section);
student.getStudentSections().add(studentSectionToAdd);
//section.addStudentSection(studentSectionToAdd);
}
}
but I still got the error.
I am also using CrudRepository to retrive entities from the database.
#Repository
public interface StudentRepository extends CrudRepository<Student, Long> {
Student findByName(String name);
}
This is where I call the method
#Component
public class DatabaseLoader implements CommandLineRunner {
private final StudentRepository studentRepository;
private final SectionRepository sectionRepository;
private final StudentSectionRepository studentSectionRepository;
private final StudentService studentService;
#Autowired
public DatabaseLoader(StudentRepository studentRepository, SectionRepository sectionRepository, StudentSectionRepository studentSectionRepository,
StudentService studentService) {
this.studentRepository = studentRepository;
this.sectionRepository = sectionRepository;
this.studentSectionRepository = studentSectionRepository;
this.studentService = studentService;
}
#Override
public void run(String... strings) throws Exception {
//Testing entities
Student student = new Student();
student.setAlbum(1L);
student.setName("student");
student.setSurname("test");
this.studentRepository.save(student);
Section section = new Section();
section.setName("section");
section.setSizeOfSection(10);
section.setIsActive(true);
this.sectionRepository.save(section);
//end
//Adding Student to a Section test
Student student1 = studentRepository.findByName("student");
//student1.setStudentSections(this.studentSectionRepository.findAllByStudent(student1));
Section section1 = sectionRepository.findByName("section");
//section1.setStudentSections(this.studentSectionRepository.findAllByStudent(student1));
studentService.addSection(student1, section1);
this.studentRepository.save(student1);
//end test
}
}
Also when I retrive StudentSection lists from the database here and set them im both objects before adding a new relationship it works fine, but this is not really the solution I am going for.
The problem is that every call from the run() method to studentRepository and studentService are separate sessions/transactions.
It's virtually as-if you did this:
...
beginTransaction();
this.studentRepository.save(student);
commit();
...
beginTransaction();
this.sectionRepository.save(section);
commit();
beginTransaction();
Student student1 = studentRepository.findByName("student");
commit();
beginTransaction();
Section section1 = sectionRepository.findByName("section");
commit();
// This does it's own transaction because of #Transactional
studentService.addSection(student1, section1);
beginTransaction();
this.studentRepository.save(student1);
commit();
Since transaction = session here, it means that student1 is detached, and that the lazy-loaded studentSections collection cannot be loaded on-demand outside the session, and hence the code fails.
Inserting a new student and a new section and associating them should really be one transaction, so if a later step fails, it's all rolled back.
Which basically means that you want the entire run() method to be one transaction, so in your case, it is the run() method that should be #Transactional, not the addSection() method.
Generally, in a 3-tiered approach, you would put transaction boundaries on service layer:
Presentation tier. This is #Controller classes, or the run() method for a simple command-line program.
Logic tier. This is #Service classes. This is where you put #Transactional, so each service call is an atomic transaction, i.e. it either succeeds or it fails, as far as the database updates are concerned, no half updates.
Data tier. This is #Repository and #Entity classes.
As such, you should keep the instantiation and initialization of the Student and Section objects in the run() method, but the rest of the code, incl. save(), should be moved to a single method in a #Service class.
About this
#Transactional(propagation=Propagation.REQUIRED, readOnly=true, noRollbackFor=Exception.class)
public void addSection(Section section){
#Transactional works only for spring-managed beans and Entities are not managed by spring.
You get this exception because you try load a lazy relations outside a session (because your entity is actually in detached-state).
To re-attach --> entityManager.merge(student);
But the best thing to do is to load the relation at query-time. By using EntityGraph for example -->
#EntityGraph(attributePaths="studentSections")
Student findByName(String name);
I have two Eclipse Projects with two Entities (Customer and Cart).
Projekt CustomerMicroService:
#Entity
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int customerId;
private String name;
private String address;
#OneToOne
#JoinColumn(name = "cart_test")
private Cart cart;
public Customer(Cart cart) {
this.cart = cart;
Project CartMicroService:
#Entity
public class Cart {
#Id
#JoinColumn(name = "cart_id")
private int cartId;
private Map<Integer, CartItem> cartItems;
private int numberOfArticles;
public Cart() {
cartItems = new HashMap<Integer, CartItem>();
numberOfArticles = 0;
}
I am getting this error:
org.hibernate.AnnotationException: #OneToOne or #ManyToOne on de.leuphana.customer.component.behaviour.Customer.cart references an unknown entity: de.leuphana.cart.component.behaviour.Cart
How do I connect those two Entities? I am expecting something like this in my Database:
<item>
<customerId>1000</customerId>
<name>name</name>
<address>email#email.com</address>
<cart_test>Cart</cart_test>
<!-- OR something like -->
<cart_id>CartId</cart_id>
This is my Spring Boot Application:
#SpringBootApplication
public class CustomerApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerApplication.class, args);
}
}
You cannot do this. Hibernate expects used model to be mapped. Mapping it in other project doesn't give any error to the outer world as it can be sealed in any way.
The workaround would be to define your model in some module, that would be shared by your projects.
I have 2 entities in my DB with one-to-one one directional mapping:
User and PasswordResetToken. The idea behind this is to create new token each time user requests password reset and store only the latest one.
Below are my entities:
#Entity
#Table(name = "USERS")
#Getter #Setter
public class User implements Serializable {
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.AUTO, generator = "usersSeq")
#SequenceGenerator(name = "usersSeq", sequenceName = "SEQ_USERS", allocationSize = 1)
private long id;
#Column(name = "NAME")
private String name;
#Column(name = "PASSWORD")
private String password;
#Column(name = "EMAIL")
private String email;
#Column(name = "ROLE")
private Integer role;
}
///...
#Entity
#Table(name = "PASSWORD_RESET_TOKENS")
#Getter
#Setter
public class PasswordResetToken implements Serializable {
private static final int EXPIRATION = 24;
#Column(name = "TOKEN")
private String token;
#Id
#OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(nullable = false, name = "user_id")
private User user;
#Column(name = "EXPIRY_DATE")
private Instant expiryDate;
public PasswordResetToken() {
}
public void setExpiryDate(ZonedDateTime expiryDate) {
this.expiryDate = expiryDate.plus(EXPIRATION, ChronoUnit.HOURS).toInstant();
}
}
Also, I have DTOs created for both of them to pass them around my app.
Code snippets:
#Getter #Setter
public class PasswordResetTokenModel {
private String token;
private ZonedDateTime expiryDate;
private UserModel user;
}
UserModel is also used for Spring Security
#Getter
#Setter
public class UserModel extends User {
public UserModel(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
private long id;
private String name;
public String getEmail() {
return this.getUsername();
}
}
For population I've created 2 populators:
#Component
public class UserPopulatorImpl implements UserPopulator {
#Autowired
UserDetailsService userDetailsService;
#Override
public UserModel populateToDTO(User user) {
UserModel userModel = new UserModel(user.getEmail(), user.getPassword(), userDetailsService.getAuthorities(user.getRole()));
userModel.setId(user.getId());
return userModel;
}
#Override
public User populateToDAO(UserModel userModel) {
User user = new User();
user.setEmail(userModel.getEmail());
user.setName(userModel.getName());
user.setPassword(userModel.getPassword());
//TODO: change it!
user.setRole(1);
return user;
}
}
//...
#Component
public class PasswordResetTokenPopulatorImpl implements PasswordResetTokenPopulator {
#Autowired
UserPopulator userPopulator;
#Override
public PasswordResetTokenModel populateToDTO(PasswordResetToken passwordResetToken) {
PasswordResetTokenModel passwordResetTokenModel = new PasswordResetTokenModel();
passwordResetTokenModel.setUser(userPopulator.populateToDTO(passwordResetToken.getUser()));
passwordResetTokenModel.setToken(passwordResetToken.getToken());
passwordResetTokenModel.setExpiryDate(ZonedDateTime.ofInstant(passwordResetToken.getExpiryDate(), ZoneId.systemDefault()));
return passwordResetTokenModel;
}
#Override
public PasswordResetToken populateToDAO(PasswordResetTokenModel passwordResetTokenModel) {
PasswordResetToken passwordResetToken = new PasswordResetToken();
passwordResetToken.setExpiryDate(passwordResetTokenModel.getExpiryDate());
passwordResetToken.setUser(userPopulator.populateToDAO(passwordResetTokenModel.getUser()));
passwordResetToken.setToken(passwordResetTokenModel.getToken());
return passwordResetToken;
}
}
I'm saving object using
sessionFactory.getCurrentSession().saveOrUpdate(token);
When I use this code, I'm getting following exception
object references an unsaved transient instance - save the transient instance before flushing: com.demo.megaevents.entities.User
There are currently 2 issues in this code:
Seems like Cascade.ALL in my OneToOne mapping is not working. If
I create separate primary key in Token class everything works almost
as expected but storing every created token in DB (more like
OneToMany relation), however I want to avoid it as I need to store
only one token per user in my DB
I don't like using new in populators, as it forces hibernate to create new object while flushing session. However, I also don't want to do another select to fetch this data from DB because just before mentioned populator I already do this query to fetch it and I think that it's an overhead.
Also, I really want to have DTOs and I don't want to remove DTO layer.
So, my questions:
What is the correct way to handle population between DTO and entities?
Are there any other improvements (probably architectural) to my solution?
Thanks a lot.
I'm not sure why you would let UserModel extend User, but I guess you did that because you didn't want to have to copy all properties from User into UserModel. Too bad, because that's what is going to be needed to have a clean separation between the entity model and data transfer model.
You get that exception because you try to persist a PasswordResetToken that has a reference to a User object with an id, but the User isn't associated with the current session. You don't have to query the user, but at least association it with the session like this:
PasswordResetToken token = // wherever you get that from
Session s = sessionFactory.getCurrentSession();
token.setUser(s.load(User.class, token.getUser().getId());
s.persist(token);
Cascading would cause the User to be created/inserted or updated via a SQL INSERT or UPDATE statement which is apparently not what you want.
You could do the Session.load() call in you populators if you want, but I'd not do that. Actually I would recommend not having populators at all, but instead create the entity objects in your service instead.
Normally you only have a few(mostly 1) ways of actually creating a new entity object, so the full extent of the transformation from DTO to entity will only be relevant in very few cases.
Most of the time you are going to do an update and for that, you should first select the existing entity and apply the fields that are allowed to be changed from the DTO on the entity object.
For providing the presentation layer with DTOs I would recommend using Blaze-Persistence Entity Views to avoid the manual mapping boilerplate and also improve performance of select queries.