Spring elasticsearch how to generate mapping for all the fields? - java

I have a Person class:
#Document(indexName = "person")
#Data
#EqualsAndHashCode(callSuper = true)
public class Person extends BaseEntity implements Serializable {
#Field(type=FieldType.Keyword)
private String firstName;
#Field(type=FieldType.Keyword)
private String lastName;
#MultiField(
mainField = #Field(type = FieldType.Keyword),
otherFields = {
#InnerField(type = FieldType.Text, suffix = "ngrams", analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
})
private String fullName;
#Field
private String maidenName;
}
I have an existing code that creates an index during startup:
final IndexOperations indexOperations = this.elasticsearchOperations.indexOps(clazz);
indexOperations.putMapping();
Now, I have a requirement to generate mappings from it and create mappings once. Can somebody help how can I integrate it with the existing code to include mappings of the fields to make them static?

Just check if the index needs to be created, if so, create it and write the mapping:
indexOperations = operations.indexOps(entityClass);
if (!indexOperations.exists()) {
indexOperations.createWithMapping();
}

Related

querydsl how to return dto list?

i use querydsl, hibernate
i want select data by Dto in Dto list but not working
here is my code
#Data
#Entity
public class Team {
#Id
#GeneratedValue
private Long id;
private String name;
#OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
}
#Entity
#Setter
public class Member {
#Id
#GeneratedValue
private Long id;
private String name;
#ManyToOne
#JoinColumn(name = "team_id")
private Team team;
}
#Setter
public class TeamDto {
private Long id;
private String name;
private List<MemberDto> members = new ArrayList<>();
}
#Setter
public class MemberDto {
private Long id;
private String name;
}
test
#BeforeEach
void setup() {
queryFactory = new JPAQueryFactory(em);
Team team = new Team();
team.setName("teamA");
em.persist(team);
Member member = new Member("memberA");
member.setTeam(team);
em.persist(member);
Member member2 = new Member("memberB");
member2.setTeam(team);
em.persist(member2);
em.flush();
em.clear();
}
#Test
void t1() {
TeamDto teamDto = queryFactory
.select(Projections.fields(
TeamDto.class,
team.id,
team.name,
Projections.fields(
MemberDto.class,
member.id,
member.name
).as("members")
))
.from(team)
.fetchOne();
System.out.println("teamDto = " + teamDto);
}
error log is = java.lang.IllegalArgumentException: com.blog.querydsltest.domain.dto.MemberDto is not compatible with java.util.List
what is problem?? is impossible bring data by List dto??
i try to change Projections.fields to bean, construct, ... but not working
how can i do ?
Multi level aggregations are currently not supported by QueryDSL. There are also no concrete plans to support it as of now.
For a DTO solution that can fetch associations with it, I recommend you to have a look at Blaze-Persistence Entity Views. With Entity Views the code for your DTO would look something like the following:
#EntityView(Team.class)
public interface TeamDto {
#IdMapping public Long getId();
#Mapping("name") public String getName();
#Mapping("members") public List<MemberDTO> getMembers();
}
If members is not an association on your TeamEntity, you can map it through a #MappingCorrelated binding.
Disclaimer: I am a contributor for Hibernate, QueryDSL and Blaze-Persistence.

Apply i18n to a Hibernate backed Spring Web API

I have a couple of Hibernate entities stored in a DB that I want to internationalize.
For example my "country" entity:
#Table(name = "country")
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Integer id;
#Column(name = "name")
private String name;
}
What I now want to do is enhance the API that handles the retrieval of the countries to return the country entry in the appropriate language. (e.g. adding ?lang=en to the query)
For that I have a country controller:
#RestController
#Api(tags = "Country")
public class CountryController {
private final CountryDao countryDao;
public CountryController(CountryDao countryDao) {
this.countryDao = countryDao;
}
#ApiOperation(value = "View a list of available countries.")
#GetMapping(path = "/entity/countries")
public Iterable<Country> getCountries() {
return countryDao.findAll();
}
}
How would I do that?
I have thought of adding a new i18n table that holds message keys with the available translations.
But in the end I still would like the API to return a simple JSON entry containing only the country name that the user is interested in, without having to attach all available translations.
I tried with AttributeConverter to mark the fields on the entity with #Convert(converter = I18nConverter.class)and search the i18n table for the matching key, but with that approach I don't have access to the specified language in the query...
public class I18nConverter implements AttributeConverter<String, String> {
private final I18nEntryDao i18nEntryDao;
#Override
public String convertToDatabaseColumn(String attribute) {
...
}
#Override
public String convertToEntityAttribute(String dbData) {
...
}
}

hibernate filter not working in the case of session.get() but working in the case of session.createQuery()

I am using hibernate 4. I am writing a filter. The strange thing I noticed is the filter is not getting applied if I use session.get() method
public SecurityAgency getSecurityAgencyById(int id) {
Session session = this.sessionFactory.getCurrentSession();
session.enableFilter("byEnabled");
SecurityAgency s = (SecurityAgency)session.get(SecurityAgency.class, new Integer(id));
return s;
}
Filter starts working as soon as I replace the session.get method with session.createQuery method and send a HQL query. I am unable to find any reason for this behaviour in the hibernate documentation.
FIlter declaration in securtiy agency class
#Entity
#Table(name="security_agency")
public class SecurityAgency implements java.io.Serializable {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name="name")
private String name;
#Column(name="code")
private String code;
#Column(name="website")
private String website;
#Column(name="tan")
private String tan;
#Column(name="email")
private String email;
#Column(name="pan")
private String pan;
#Column(name="created_at")
private Date createdAt;
#Column(name="created_by")
private long createdBy;
#Column(name="modified_at")
private Date modifiedAt;
#Column(name="modified_by")
private long modifiedBy;
#OneToMany(mappedBy="securityAgency",fetch = FetchType.EAGER)
#JsonIgnoreProperties("securityAgency")
#Filter(name = "byEnabled", condition = "is_enabled= 1")
private Set<ContactPerson> contactPersons = new HashSet<ContactPerson>(0);
public SecurityAgency() {
}
Contact person class
#Entity
#Table(name = "contact_person")
#FilterDefs({
#FilterDef(name="byEnabled"),
#FilterDef(name="bySecurityAgency",parameters = #ParamDef(name="agency_id", type="int"))
})
#Filters({
#Filter(name="byEnabled", condition = "is_enabled = 1"),
#Filter(name="bySecurityAgency", condition = "agency_id= :agency_id ")
})
public class ContactPerson implements java.io.Serializable {
Filter doesn't work if you are fetching using id value.Use Query interface instead. See this thread
if you want to use table column values you need to use filter join table ( #FilterJoinTable ), #Filter is applied to target entity rather than table
try,
#FilterJoinTable(name = "byEnabled", condition = "is_enabled= :enabled")
private Set<ContactPerson> contactPersons = new HashSet<ContactPerson>(0);
get
session.enableFilter("byEnabled").setParameter("enabled", Integer.valueOf(1));

Serialize JSON Subclasses Information in Java

I need some help with one JSON serialization Problem.
I have one class like this:
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorFormula("type")
#JsonSubTypes({ #JsonSubTypes.Type(value =TextFileCardEntity.class, name = "textCard"),
#JsonSubTypes.Type(value = MultipleChoiceFileCard.class, name = "choiceCard")#JsonSubTypes.Type(value = MultipleChoiceFileCard.class, name = "choiceCard")})
public class FileCardEntity extends ResourceEntity implements Cloneable {
#NotNull
#JsonIgnore
private FileCardType type;
private Date expirationDate;
.....
I also have two classes that extends of FileCardEntity:
#JsonTypeName(value = "textCard")
public class TextFileCardEntity extends FileCardEntity {
#Lob
#Type(type = "org.hibernate.type.TextType")
private String question;
#Lob
#Type(type = "org.hibernate.type.TextType")
private String answer;
.......
AND
#Entity
#DiscriminatorValue("1")
#JsonTypeName(value = "choiceCard")
public class MultipleChoiceFileCard extends FileCardEntity {
#Lob
#Type(type = "org.hibernate.type.TextType")
private String question;
#Lob
#Type(type = "org.hibernate.type.TextType")
private String crib;
......
I use the next Code in order to deserialize the information:
ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
final ObjectWriter typedWriter = mapper.writerWithType(mapper.getTypeFactory().constructCollectionType(List.class, classElement));
System.out.println(typedWriter.writeValueAsString(elements));
Where elements is: List<?> elements
When I deserialize information from Server about TextFileCardEntity, I get:
[{"textCard":{"status":"ACTIVE","lastModified":1366293513200,"expirationDate":0.....
That is ok
When I attempt serialize information about TextFileCardEntity for example to Server, the code sends:
[{"FileCardEntity":{"status":"ACTIVE","lastModified":1366378327069,"shared":false,"orderID":0........
That is not ok because I need the syntax to be similar has in the deserialization information
--> [{"textCard":{"status".... and not [{"FileCardEntity":{"status"....
What can I do?

Hibernate criteria: search by content on a property list in an entity

I want to search by content on a property in an entity
I have a simple class to define a User:
#Entity
public class User {
#Id
#Column(name = "pers_id")
private int persId;
#Column(name = "full_name")
private String fullName;
#OneToMany
#JoinColumn(name = "PERS_ID")
private List<UserLanguages> languages = new ArrayList<UserLanguages>();
}
A User can have multiple languages, here is the class to make the link between user and a language.
#Entity
public class UserLanguages {
#Column(name="pers_id")
private int persId;
#Id
#Column(name="lang_iso_code")
private String langISO;
#Column(name="lang_full_name")
private String langFullName;
#Column(name="order_seq")
private int order;
}
#Entity
public class Language {
#Id
#Column(name="ID")
private long id;
#Column(name = "CODE")
private String code;
}
I have created a object to do search:
public class UserFilter {
private String name;
private List<Language> languages;
}
I have defined a service:
#Service("userService")
public class UserServiceImpl implements UserService {
#Override
public List<User> findByFilter(UserFilter userFilter) {
final Criteria criteria = userDao.createCriteria();
if (userFilter.getName() != null) {
for (final String token : userFilter.getName().toLowerCase().trim().split(" ")) {
criteria.add(Restrictions.like("fullName", "%" + token + "%"));
}
}
if (null != userFilter.getLanguages() && userFilter.getLanguages().size() > 0) {
final List<String> contents = new ArrayList<String>(userFilter.getLanguages().size());
for (final Language lang : userFilter.getLanguages()) {
contents.add(lang.getCode());
}
criteria.add(Restrictions.in("languages", contents));
}
return userDao.findByCriteria(criteria);
}
My question is how can I do search on languages. I want to find all users with this or thoses languages defined in the userFilter param.
The part about languages doesn't work in the method findByFilter in the service. Can you help me?
First of all, the UserLanguages entity should be named UserLanguage : it represents one language, and not several.
Then, the pers_id column is a foreign key to the User entity. It should thus be mapped as a ManyToOne relationship to the User entity rather than a basic column.
Finally, and to answer your question (I'll assume you want to find the users having at least one user language whose langISO code is in the contents list) : you should use a join :
// inner join between User and UserLanguages
criteria.createAlias("languages", "userLanguage");
// restriction on the langISO property of UserLanguage
criteria.add(Restrictions.in("userLanguage.langIso", contents));

Categories