I am trying to delete an index from the database that I put before.
#Indexed(unique = true)
private String name;
After I delete the #Indexed(unique = true), I need to remove it from the MongoDB too. And I need to do it within the Spring. Can I do it with #PostConstruct or something?.
Spring-Data's MongoTemplate has a method to give you IndexOperations for a collection which lets you create and drop indices of a collection.
Attention:
According to db.collection.dropIndex() documentation the drop of a index will lock the whole collection until its dropped and all queries using the index are killed.
Here is an example which deletes an index 'name' from the collection 'products' during app start.
#Component
class IndexManager implements InitializingBean {
private MongoTemplate mongoTemplate;
public IndexManager(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
#Override
public void afterPropertiesSet() {
mongoTemplate.indexOps("products").dropIndex("name");
}
}
There are multiple ways to execute code during spring application startup. More ways to do it can be found here: running-setup-logic-on-startup-in-spring
I solve this with using #PostConstruct. While app is initializing I did remove the index with MongoTemplates. The Code is like this:
#PostConstruct
private void removeIndex() {
IndexOperations indexOperations = mongoTemplate.indexOps(YourEntity.class);
Optional<IndexInfo> indexInfo = indexOperations.getIndexInfo().stream().filter(i->i.getName().equals("name")).findFirst();
if(indexInfo.isPresent()) {
indexOperations.dropIndex("name");
}
}
Related
Environment:
spring-boot v2.0.4 RELEASE
spring-data-aerospike v2.0.1.RELEASE
java - 8
Here are my application code and properties.
// application.properties
aerospike.hosts=xxx:3000
aerospike.namespace=test
// aerospike configuration class
#Configuration
#RequiredArgsConstructor
#EnableConfigurationProperties(AerospikeConfiguration.AerospikeConfigurationProperties.class)
#EnableAerospikeRepositories(basePackageClassses = TestAeroRepository.class)
public class AerospikeConfiguration extends AbstractAerospikeDataConfiguration {
private final AerospikeConfigurationProperties aerospikeConfigurationProperties;
#Override
protected Collection<Host> getHosts() {
return Host.parseServiceHosts(aerospikeConfigurationProperties.getHosts());
}
#Override
protected String nameSpace() {
return aerospikeConfigurationProperties.getNamespace();
}
#Data
#Validate
#ConfigurationProperties("aerospike")
public static class AerospikeConfigurationProperties {
#NotEmpty
String hsots;
#NotEmpty
String namespace;
}
}
# Entity class
#Value
#Document
#Builder(toBuilder = true)
#AllArgsConstructor
public class testEntity() {
#Id
int id;
#Field
String name;
#Field
String timestamp;
}
#Repository
public interface TestAeroRepository extends AerospikeRepository<TestEntity, Integer> {
}
public interface TestAeroService {
void save();
}
#Service
#RequiredArgsConstructor
public class TestAeroServiceImpl implements TestAeroService {
private final TestAeroRepository testAeroRepository;
#Override
public void save(TestEntity entity) {
testAeroRepository.save(entity);
}
}
I checked Aerospike client connection has no problem.
But error is occurred when save() method is executed.
org.springframework.cglib.core.ReflectUtils.defineClass(Ljava/lang/String;[BLjava/lang/ClassLoader;Ljava/security/ProtectionDomain;Ljava/lang/Class;)Ljava/lang/Class;
Have to make sets before execute the application? I didn't make sets.
Any problem with my code?
You’re using an old version of spring-data-aerospike (2.0.1.RELEASE was released on April 2019) is there any chance you can upgrade to the latest version? 2.4.2.RELEASE
You can see how to setup a simple spring data aerospike application here: https://medium.com/aerospike-developer-blog/simple-web-application-using-java-spring-boot-aerospike-database-and-docker-ad13795e0089
Please share the entire project’s code and the entire exception.
I would look into:
The configuration class (The Aerospike Beans creation).
The content of the testEntity class - are you using #Id annotation on the primary key field?
Extending the repository class with specifying the testEntity object (… extends AerospikeRepository<testEntity, Object> {) you can see an example in the link I added.
The set is automatically created and takes the name of your object class, which is testEntity in your case. For example, based on your code, if you do not specify a collection in the #Document annotation a set named "testEntity" will automatically be created. I added the #Document(collection = "testEntitys") annotation and all I did was create two set. Once you insert your first record, run the "SHOW SETS" aql command and it will be there. So that's one way to do it.
I am using spring boot starter 2.1.6 and spring-data-mongo starter version is 2.1.6.RELEASE.
Whenever the server starts i understood spring boot mongo creates the collection schema. For some reason spring boot mongo does not create collection schema for some specific collection. These collections are all the time same ones.
But when i create programatically by myself they are created without error or warning.
mongoTemplate.createCollection("collectionName");
I would like to know how to find out why spring boot is not able to
create these specific collections.
For example below is one of the collection which is not created automatically by spring boot.
#Document(collection = "subscription_histories")
public class SubscriptionHistoryModel extends AbstractModel {
private static final long serialVersionUID = 4424861457985412905L;
#NotNull
#DBRef(lazy = true)
#Field("customer")
private CustomerModel customer;
#NotNull
#Field("subscription_from")
private Instant subscriptionFrom;
#NotNull
#Field("subscription_to")
private Instant subscriptionTo;
public CustomerModel getCustomer() {
return customer;
}
public void setCustomer(CustomerModel customer) {
this.customer = customer;
}
public Instant getSubscriptionFrom() {
return subscriptionFrom;
}
public void setSubscriptionFrom(Instant subscriptionFrom) {
this.subscriptionFrom = subscriptionFrom;
}
public Instant getSubscriptionTo() {
return subscriptionTo;
}
public void setSubscriptionTo(Instant subscriptionTo) {
this.subscriptionTo = subscriptionTo;
}
#Override
public int hashCode() {
return super.hashCode();
}
#Override
public boolean equals(Object obj) {
return super.equals(obj);
}
}
I've been struggling on this issue for past 2 days as well. Finally found why was this happening.
So if you're using docker for the mongodb and mongodb express. Idk for some reason the data is being stored locally and accessed from there and not the mongodb docker container. I've also installed mongodb locally and was trying to run using docker as well.
So, you must check if there are any other places where your mongodb service might be running and your program might be referring to that place!
I'm trying to create a repository that has a method which doesn't fit the usual JpaRepository with #Query annotations.
I've created a custom repository interface:
public interface CustomVoteRepository {
List<VoteCountResult> countVotesForSession();
}
And the implementation:
#Repository
public class CustomVoteRepositoryImp implements CustomVoteRepository {
private JdbcTemplate jdbcTemplate;
public CustomVoteRepositoryImp(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
#Override
public List<VoteCountResult> countVotesForSession() {
return jdbcTemplate.query("SELECT video_id, COUNT(votes.id) FROM votes WHERE session_id=2 GROUP BY video_id",
new CustomRowMapper());
}
}
However, this gives me this error:
No property countVotesForSession found for type Vote!
I don't understand why it's trying to map a property on the Vote class. I understand it does this for the "auto-generated" method names, but this is supposed to be a custom one.
I've come across this article: https://www.mkyong.com/spring-data/spring-data-add-custom-method-to-repository/ which explains what I'm doing, and yet it's trying to map a property of the model for a custom repository.
I'm sure I missed something stupid.
Thanks!
Edit:
Here's the VoteCountResult dto:
#Data
#AllArgsConstructor
public class VoteCountResult {
private String count;
private String title;
private String url;
}
What if you change your custom method name to votesForSessionCount ? I think this way you won't face with method name conflict.
In a Spring bean, I need to process a configuration property before using is, e.g.:
#Component
class UsersController {
#Value("${roles}")
private String rolesAsString;
private List<String> roles;
#PostConstruct
public void initRoles() {
// just an example, not necessarily string splitting
roles = rolesAsString.split(",");
}
This works, but I am left with an unneeded member variable 'rolesString'. What would be a clean concise way to only keep the processed value?
Properties is
roles=role1,role2,role3
Code is :
#Value("#{'${roles}'.split(',')}")
private List<String> roles;
I am using hateoas for implementing links in my repositories.So my Customer Class extends ResourceSupport which has private final List<Link> links; and in constructor
public ResourceSupport() {
this.links = new ArrayList<Link>();
}
So when I am saving customer entity using Mongo template mongoTemplate.save(customer);
So when I see the documents in Mongo db it shows
{
_id:"objectid(57vsdsjdsk),
firstName:"Yamini",
lastName:"Tyagi"
links as empty Array List(initialized in constructor)
}
So how would I avoid links to be persisted in Mongo database?
Please help on this?
I have overloaded the get method of that property in my child class and marked that as #Transient
Using the #Transient annotation that particular property will not save in Database. Hope this will help
#Override
#Transient
public java.util.List<org.springframework.hateoas.Link> getLinks() {
return super.getLinks();
}